TITLE	BASIC M6502 8K VER 1.1 BY MICRO-SOFT ; 标题：M6502 8K版本1.1，由微软开发
SEARCH	M6502 ; 搜索M6502相关定义
SALL ; 抑制宏展开列表
RADIX 10			;THROUGHOUT ALL BUT MATH-PAK. ; 除数学包外全程使用十进制

$Z::				;STARTING POINT FOR M6502 SIMULATOR ; M6502模拟器起始点
	ORG	0		;START OFF AT LOCATION ZERO. ; 从地址0开始
SUBTTL	SWITCHES,MACROS. ; 子标题：开关和宏

REALIO=4			;5=STM ; 5=STM
				;4=APPLE. ; 4=APPLE
				;3=COMMODORE. ; 3=COMMODORE
				;2=OSI ; 2=OSI
				;1=MOS TECH,KIM ; 1=MOS Technology, KIM
				;0=PDP-10 SIMULATING 6502 ; 0=PDP-10模拟6502
INTPRC==1			;INTEGER ARRAYS. ; 整数数组
ADDPRC==1			;FOR ADDITIONAL PRECISION. ; 用于额外精度
LNGERR==0			;LONG ERROR MESSAGES. ; 长错误信息
TIME==	0			;CAPABILITY TO SET AND READ A CLK. ; 设置和读取时钟的能力
EXTIO== 0			;EXTERNAL I/O. ; 外部I/O
DISKO== 0			;SAVE AND LOAD COMMANDS ; 保存和加载命令
NULCMD==1			;FOR THE "NULL" COMMAND ; 用于“NULL”命令
GETCMD==1
RORSW==1
ROMSW==1			;TELLS IF THIS IS ON ROM. ; 指示是否在ROM上
CLMWID==14
LONGI==1			;LONG INITIALIZATION SWITCH. ; 长初始化开关
STKEND=511
BUFPAG==0
LINLEN==72			;TERMINAL LINE LENGTH. ; 终端行长度
BUFLEN==72			;INPUT BUFFER SIZE. ; 输入缓冲区大小
ROMLOC= ^O20000			;ADDRESS OF START OF PURE SEGMENT. ; 纯段起始地址
KIMROM=1
IFE	ROMSW,<KIMROM==0> ; 如果ROMSW为0，则KIMROM设为0
IFN	REALIO-1,<KIMROM==0> ; 如果REALIO不等于1，则KIMROM设为0
IFN	ROMSW,<
RAMLOC= ^O40000			;USED ONLY IF ROMSW=1 ; 仅当ROMSW=1时使用
IFE	REALIO,<ROMLOC= ^O20000 ;START AT 8K. ; 从8K开始
	RAMLOC=^O1400>> ; RAM位置
IFE	REALIO-3,< ; 如果REALIO等于3（Commodore）
	DISKO==1
	RAMLOC==^O2000
	ROMLOC=^O140000
	NULCMD==0
	GETCMD==1
	linlen==40
	BUFLEN==81
	CQOPEN=^O177700
	CQCLOS=^O177703
	CQOIN= ^O177706		;OPEN CHANNEL FOR INPUT ; 打开输入通道
	CQOOUT=^O177711		;FILL FOR COMMO. ; 为通信填充
	CQCCHN=^O177714
	CQINCH=^O177717		;INCHR'S CALL TO GET A CHARACTER ; INCHR调用以获取字符
	OUTCH= ^O177722
	CQLOAD=^O177725
	CQSAVE=^O177730
	CQVERF=^O177733
	CQSYS= ^O177736
	ISCNTC=^O177741
	CZGETL=^O177744		;CALL POINT FOR "GET" ; “GET”的调用点
	CQCALL=^O177747		;CLOSE ALL CHANNELS ; 关闭所有通道
	CQTIMR=^O215
	BUFPAG==2
	BUF==256*BUFPAG
	STKEND==507
	CQSTAT=^O226
	CQHTIM=^O164104
	EXTIO==1
	TIME==1
	GETCMD==1
	CLMWID==10
	PI=255				;VALUE OF PI CHARACTER FOR COMMODORE. ; Commodore的PI字符值
	ROMSW==1
	RORSW==1
	TRMPOS=^O306>
IFE	REALIO-1,<GETCMD==1 ; 如果REALIO等于1（KIM）
	DISKO==1
	OUTCH=^O17240			;1EA0
	ROMLOC==^O20000
	RORSW==0
	CZGETL=^O17132>
IFE	REALIO-2,< ; 如果REALIO等于2（OSI）
	RORSW==0
	RAMLOC==^O1000
IFN	ROMSW,<
	RORSW==0
	RAMLOC==^O100000>
	OUTCH==^O177013>
IFE	REALIO-4,< ; 如果REALIO等于4（APPLE）
	RORSW==1
	NULCMD==0
	GETCMD==1
	CQINLN==^O176547
	CQPRMP==^O63
	CQINCH==^O176414
	CQCOUT==^O177315
	CQCSIN==^O177375
	BUFPAG==2
	BUF=BUFPAG*256
	ROMLOC=^O4000
	RAMLOC=^O25000			;PAGE 2A ; 页面2A
	OUTCH=^O176755
	CZGETL=^O176414
	LINLEN==40
	BUFLEN==240
	RORSW==1
	STKEND=507>
IFE	RORSW,< ; 如果RORSW为0
DEFINE	ROR (WD),< ; 定义ROR宏（无ROR指令时模拟）
	LDAI	0
	BCC	.+4
	LDAI	^O200
	LSR	WD
	ORA	WD
	STA	WD>>

DEFINE ACRLF,< ; 定义回车换行宏
	13
	10>
DEFINE	SYNCHK	(Q),< ; 定义语法检查宏
	LDAI	<Q>
	JSR	SYNCHR>
DEFINE	DT(Q),< ; 定义数据表宏
IRPC	Q,<IFDIF <Q><">,<EXP "Q">>>
DEFINE	LDWD	(WD),< ; 加载字（16位）到A和Y
	LDA	WD
	LDY	<WD>+1>
DEFINE	LDWDI	(WD),< ; 立即数加载字到A和Y
	LDAI	<<WD>&^O377>
	LDYI	<<WD>/^O400>>
DEFINE	LDWX	(WD),< ; 加载字到A和X
	LDA	WD
	LDX	<WD>+1>
DEFINE	LDWXI	(WD),< ; 立即数加载字到A和X
	LDAI	<<WD>&^O377>
	LDXI	<<WD>/^O400>>
DEFINE	LDXY	(WD),< ; 加载字到X和Y
	LDX	WD
	LDY	<WD>+1>
DEFINE	LDXYI	(WD),< ; 立即数加载字到X和Y
	LDXI	<<WD>&^O377>
	LDYI	<<WD>/^O400>>
DEFINE	STWD	(WD),< ; 存储A和Y到字
	STA	WD
	STY	<WD>+1>
DEFINE	STWX	(WD),< ; 存储A和X到字
	STA	WD
	STX	<WD>+1>
DEFINE	STXY	(WD),< ; 存储X和Y到字
	STX	WD
	STY	<WD>+1>
DEFINE	CLR	(WD),< ; 清除字
	LDAI	0
	STA	WD>
DEFINE	COM	(WD),< ; 取反字
	LDA	WD
	EORI	^O377
	STA	WD>
DEFINE	PULWD	(WD),< ; 从堆栈弹出字
	PLA
	STA	WD
	PLA
	STA	<WD>+1>
DEFINE	PSHWD	(WD),< ; 压字到堆栈
	LDA	<WD>+1
	PHA
	LDA	WD
	PHA>
DEFINE	JEQ	(WD),< ; 等于则跳转
	BNE	.+5
	JMP	WD>
DEFINE	JNE	(WD),< ; 不等于则跳转
	BEQ	.+5
	JMP	WD>
DEFINE	BCCA(Q),<	BCC	Q>	;BRANCHES THAT ALWAYS BRANCH ; 总是分支（无条件分支）
DEFINE	BCSA(Q),<	BCS	Q>	;THESE ARE USED ON THE 6502 BECAUSE ; 这些用于6502，因为
DEFINE	BEQA(Q),<	BEQ	Q>	;THERE IS NO UNCONDITIONAL BRANCH ; 没有无条件分支指令
DEFINE	BNEA(Q),<	BNE	Q>
DEFINE	BMIA(Q),<	BMI	Q>
DEFINE	BPLA(Q),<	BPL	Q>
DEFINE	BVCA(Q),<	BVC	Q>
DEFINE	BVSA(Q),<	BVS	Q>
DEFINE	INCW(R),< ; 字递增
	INC	R
	BNE	%Q
	INC	R+1
%Q:>
DEFINE	SKIP1,	<XWD ^O1000,^O044>	;BIT ZERO PAGE TRICK. ; 位零页技巧
DEFINE	SKIP2,	<XWD ^O1000,^O054>	;BIT ABS TRICK. ; 位绝对地址技巧
IF1,< ; 第一遍汇编时
IFE	REALIO,<PRINTX/SIMULATE/> ; 如果REALIO为0，打印"SIMULATE"
IFE	REALIO-1,<PRINTX KIM> ; 如果REALIO为1，打印"KIM"
IFE	REALIO-2,<PRINTX OSI> ; 如果REALIO为2，打印"OSI"
IFE	REALIO-3,<PRINTX COMMODORE> ; 如果REALIO为3，打印"COMMODORE"
IFE	REALIO-4,<PRINTX APPLE> ; 如果REALIO为4，打印"APPLE"
IFE	REALIO-5,<PRINTX STM> ; 如果REALIO为5，打印"STM"
IFN	ADDPRC,<PRINTX ADDITIONAL PRECISION> ; 如果ADDPRC非0，打印"ADDITIONAL PRECISION"
IFN	INTPRC,<PRINTX INTEGER ARRAYS> ; 如果INTPRC非0，打印"INTEGER ARRAYS"
IFN	LNGERR,<PRINTX LONG ERRORS> ; 如果LNGERR非0，打印"LONG ERRORS"
IFN	DISKO,<PRINTX SAVE AND LOAD> ; 如果DISKO非0，打印"SAVE AND LOAD"
IFE	ROMSW,<PRINTX RAM> ; 如果ROMSW为0，打印"RAM"
IFN	ROMSW,<PRINTX ROM> ; 如果ROMSW非0，打印"ROM"
IFE	RORSW,<PRINTX NO ROR> ; 如果RORSW为0，打印"NO ROR"
IFN	RORSW,<PRINTX ROR ASSUMED>> ; 如果RORSW非0，打印"ROR ASSUMED"
PAGE
SUBTTL	INTRODUCTION AND COMPILATION PARAMETERS. ; 子标题：介绍和编译参数
COMMENT * ; 注释块开始

--------- ---- -- ---------
COPYRIGHT 1976 BY MICROSOFT
--------- ---- -- ---------
7/27/78 FIXED BUG WHERE FOR VARIABLE AT BYTE FF MATCHED RETURN SEARCHING
	FOR GOSUB ENTRY ON STACK IN FNDFOR CALL BY CHANGING STA FORPNT
	TO STA FORPNT+1. THIS IS A SERIOUS BUG IN ALL VERSIONS.
7/27/78 FIXED BUG AT NEWSTT UNDER IFN BUFPAG WHEN CHECK OF CURLIN
	WAS DONE BEFORE CURLIN SET UP SO INPUT RETRIES OF FIRST STATEMENT
	WAS GIVING SYNTAX ERROR INSTEAD OF REDO FROM START (CODE WAS 12/1/77 FIX)
7/1/78	SAVED A FEW BYTES IN INIT FOR COMMODORE (14)
7/1/78 FIXED BUG WHERE REPLACING A LINE OVERFLOWING MEMORY LEFT LINKS
	IN A BAD STATE. (CODE AT NODEL AND FINI) BUG#4
7/1/78 FIXED BUG WHERE GARBAGE COLLECTION NEVER(!) COLLECTS TEMPS
	(STY GRBPNT  AT FNDVAR, LDA GRBPNT ORA GRBPNT+1 AT GRBPAS)
	THIS WAS COMMODORE BUG #2
7/1/78 FIXED BUG WHERE DELETE/INSERT OF LINE COULD CAUSE A GARBAGE COLLECTION WITH BAD VARTAB IF OUT OF MEMORY
	 (LDWD MEMSIZ STWD FRETOP=JSR RUNC CLC ALSO AT NODEL)
3/9/78 EDIT TO FIX COMMO TRMPOS AND CHANGE LEFT$ AND RIGHT$ TO ALLOW A SECOND ARGUMENT OF 0 AND RETURN A NULL STRING
2/25/78 FIXED BUG THAT INPFLG WAS SET WRONG WHEN BUFPAG.NE.0
	INCREASED NUMLEV FROM 19 TO 23
2/11/78 DISALLOWED SPACES IN RESERVED WORDS. PUT IN SPECIAL CHECK FOR "GO TO"
2/11/78 FIXED BUG WHERE ROUNDING OF THE FAC BEFORE PUSHING COULD CAUSE A STRING POINTER
	IN THE FAC TO BE INCREMENTED
1/24/78 fixed problem where user defined function undefined check fix was smashing error number in [x]
12/1/77 FIXED PROBLEM WHERE PEEK WAS SMASHING (POKER) CAUSING POKE OF PEEK TO FAIL
12/1/77 FIXED PROBLEM WHERE PROBLEM WITH VARTXT=LINNUM=BUF-2 CAUSING BUF-1 COMMA TO DISAPPEAR
12/1/77 FIXED BUFPAG.NE.0 PROBLEM AT NEWSTT AND STOP : CODE WAS STILL
	ASSUMING TXTPTR+1.EQ.0 IFF STATEMENT WAS DIRECT
* ; 注释块结束
NUMLEV==23			;NUMBER OF STACK LEVELS RESERVED ; 保留的堆栈层数
				;BY AN EXPLICIT CALL TO "GETSTK". ; 通过显式调用"GETSTK"
STRSIZ==3			;# OF LOCS PER STRING DESCRIPTOR. ; 每个字符串描述符的位置数
NUMTMP==3			;NUMBER OF STRING TEMPORARIES. ; 字符串临时变量数量
CONTW==15			;CHARACTER TO SUPPRESS OUTPUT. ; 抑制输出的字符

PAGE
SUBTTL	SOME EXPLANATION. ; 子标题：一些解释
COMMENT * ; 注释块开始

M6502 BASIC CONFIGURES BASIC AS FOLLOWS ; M6502 BASIC配置如下

LOW LOCATIONS ; 低地址
	PAGE	ZERO ; 零页

		STARTUP: ; 启动
		INITIALLY A JMP TO INITIALIZATION CODE BUT ; 最初是跳转到初始化代码
		CHANGED TO A JMP TO "READY". ; 但改为跳转到"READY"
		RESTARTING THE MACHINE AT LOC 0 DURING PROGRAM ; 在程序执行期间在位置0重新启动机器
		EXECUTION CAN LEAVE THINGS MESSED UP. ; 可能会使事情混乱

		LOC OF FAC TO INTEGER AND INTEGER TO FAC ; FAC到整数和整数到FAC的位置
		ROUTINES. ; 例程

		"DIRECT" MEMORY: ; "直接"内存
		THESE ARE THE MOST COMMONLY USED LOCATIONS. ; 这些是最常用的位置
		THEY HOLD BOOKKEEPING INFO AND ALL OTHER ; 它们保存簿记信息和所有其他
		FREQUENTLY USED INFORMATION. ; 频繁使用的信息
		ALL TEMPORARIES, FLAGS, POINTERS, THE BUFFER AREA, ; 所有临时变量、标志、指针、缓冲区区域
		THE FLOATING ACCUMULATOR, AND ANYTHING ELSE THAT ; 浮点累加器以及任何其他
		IS USED TO STORE A CHANGING VALUE SHOULD BE LOCATED ; 用于存储变化值的东西都应位于
		IN THIS AREA. CARE MUST BE MADE IN MOVING LOCATIONS ; 此区域。在移动位置时必须小心
		IN THIS AREA SINCE THE JUXTAPOSITION OF TWO LOCATIONS ; 因为两个位置的并列
		IS OFTEN DEPENDED UPON. ; 通常被依赖

		STILL IN RAM WE HAVE THE BEGINNING OF THE "CHRGET" ; 在RAM中还有"CHRGET"的开始
		SUBROUTINE. IT IS HERE SO [TXTPTR] CAN BE THE ; 子程序。它在这里所以[TXTPTR]可以是
		EXTENDED ADDRESS OF A LOAD INSTRUCTION. ; 加载指令的扩展地址
		THIS SAVES HAVING TO BOTHER ANY REGISTERS. ; 这省去了打扰任何寄存器的麻烦

	PAGE	ONE ; 第一页
		THE STACK. ; 堆栈

	STORAGE PAGE TWO AND ON ; 存储页面二及以后
		IN RAM VERSIONS THESE DATA STRUCTURES COME AT THE ; 在RAM版本中，这些数据结构位于
		END OF BASIC. IN ROM VERSON THEY ARE AT RAMLOC WHICH ; BASIC的末尾。在ROM版本中，它们在RAMLOC
		CAN EITHER BE ABOVE OR BELOW ROMLOC, WHICH IS WHERE ; 可以在ROMLOC之上或之下，ROMLOC是
		BASIC ITSELF RESIDES. ; BASIC本身所在的位置

				A ZERO. ; 一个零
		[TXTTAB]	POINTER TO NEXT LINE'S POINTER. ; 指向下一行指针的指针
				LINE # OF THIS LINE (2 BYTES). ; 本行的行号（2字节）
				CHARACTERS ON THIS LINE. ; 本行的字符
				ZERO. ; 零
				POINTER AT NEXT LINE'S POINTER ; 指向下一行指针的指针
					(POINTED TO BY THE ABOVE POINTER). ; （由上述指针指向）
				... REPEATS ... ; ...重复...
		LAST LINE:	POINTER AT ZERO POINTER. ; 最后一行：指向零指针的指针
				LINE # OF THIS LINE. ; 本行的行号
				CHARACTERS ON THIS LINE. ; 本行的字符
				ZERO. ; 零
				DOUBLE ZERO (POINTED TO BY THE ABOVE POINTER). ; 双零（由上述指针指向）
		[VARTAB]	SIMPLE VARIABLES. 6 BYTES PER VALUE. ; 简单变量。每个值6字节
				2 BYTES GIVE THE NAME, 4 BYTES THE VALUE. ; 2字节给出名称，4字节给出值
				... REPEATS ... ; ...重复...
		[ARYTAB]	ARRAY VARIABLES. 2 BYTES NAME, 2 BYTE ; 数组变量。2字节名称，2字节
				LENGTH, NUMBER OF DIMENSIONS , EXTENT OF ; 长度，维数，每维的范围
				EACH DIMENSION (2BYTES/), VALUES ; （每维2字节），值
				... REPEATS ... ; ...重复...
		[STREND]	FREE SPACE. ; 空闲空间
				... REPEATS ... ; ...重复...
		[FRETOP]	STRING SPACE IN USE. ; 使用中的字符串空间
				... REPEATS ... ; ...重复...
		[MEMSIZ]	HIGHEST MACHINE LOCATION. ; 最高机器位置
				UNUSED EXCEPT BY THE VAL FUNCTION. ; 除VAL函数外未使用

		ROM -- CONSTANTS AND CODE. ; ROM -- 常量和代码

	FUNCTION DISPATCH ADDRESSES (AT ROMLOC) ; 函数分派地址（在ROMLOC）
		"FUNDSP" CONTAINS THE ADDRESSES OF THE ; "FUNDSP"包含
		FUNCTION ROUTINES IN THE ORDER OF THE ; 函数例程的地址，按
		FUNCTION NAMES IN THE CRUNCH LIST. ; CRUNCH列表中的函数名称顺序
		THE FUNCTIONS THAT TAKE MORE THAN ONE ARGUMENT ; 接受多个参数的函数
		ARE AT THE END. SEE THE EXPLANATION AT "ISFUN". ; 在末尾。参见"ISFUN"处的解释

	THE OPERATOR LIST ; 运算符列表
		THE "OPTAB" LIST CONTAINS AN OPERATOR'S PRECEDENCE ; "OPTAB"列表包含运算符的优先级
		FOLLOWED BY THE ADDRESS OF THE ROUTINE TO PERFORM ; 后跟执行操作的例程地址
		THE OPERATION. THE INDEX INTO THE ; 操作。进入
		OPERATOR LIST IS MADE BY SUBTRACTING OFF THE CRUNCH VALUE ; 运算符列表的索引是通过减去
		OF THE LOWEST NUMBERED OPERATOR. THE ORDER ; 最小编号运算符的CRUNCH值来实现的。顺序
		OF OPERATORS IN THE CRUNCH LIST AND IN "OPTAB" IS IDENTICAL. ; CRUNCH列表和"OPTAB"中的运算符顺序相同
		THE PRECEDENCES ARE ARBITRARY EXCEPT FOR THEIR ; 优先级是任意的，除了它们的
		COMPARATIVE SIZES. NOTE THAT THE PRECEDENCE FOR ; 相对大小。请注意
		UNARY OPERATORS SUCH AS "NOT" AND NEGATION ARE ; 一元运算符（如"NOT"和取反）的优先级
		SETUP SPECIALLY WITHOUT USING THE LIST. ; 是特殊设置的，不使用列表

	THE RESERVED WORD OR CRUNCH LIST ; 保留字或CRUNCH列表
		WHEN A COMMAND OR PROGRAM LINE IS TYPED IN ; 当输入命令或程序行时
		IT IS STORED IN "BUF". AS SOON AS THE WHOLE LINE ; 它被存储在"BUF"中。一旦整行
		HAS BEEN TYPED IN ("INLIN" RETURNS) "CRUNCH" IS ; 输入完成（"INLIN"返回），"CRUNCH"被
		CALLED TO CONVERT ALL RESERVED WORDS TO THEIR ; 调用来将所有保留字转换为其
		CRUNCHED VALUES. THIS REDUCES THE SIZE OF THE ; CRUNCHED值。这减少了
		PROGRAM AND SPEEDS UP EXECUTION BY ALLOWING ; 程序的大小并通过允许
		LIST DISPATCHES TO PERFORM FUNCTIONS, STATEMENTS, ; 列表分派来执行函数、语句
		AND OPERATIONS. THIS IS BECAUSE ALL THE STATEMENT ; 和操作来加速执行。这是因为所有语句
		NAMES ARE STORED CONSECUTIVELY IN THE CRUNCH LIST. ; 名称都连续存储在CRUNCH列表中
		WHEN A MATCH IS FOUND BETWEEN A STRING ; 当在字符串
		OF CHARACTERS AND A WORD IN THE CRUNCH LIST ; 和CRUNCH列表中的单词之间找到匹配时
		THE ENTIRE TEXT OF THE MATCHED WORD IS TAKEN OUT OF ; 匹配单词的整个文本从
		THE INPUT LINE AND A RESERVED WORD TOKEN IS PUT ; 输入行中取出，并放入一个保留字令牌
		IN ITS PLACE. A RESERVED WORD TOKEN IS ALWAYS EQUAL ; 在其位置。保留字令牌总是等于
		TO OCTAL 200 PLUS THE POSITION OF THE MATCHED WORD ; 八进制200加上匹配单词
		IN THE CRUNCH LIST. ; 在CRUNCH列表中的位置

	STATEMENT DISPATCH ADDRESSES ; 语句分派地址
		WHEN A STATEMENT IS TO BE EXECUTED, THE FIRST ; 当要执行语句时，第一个
		CHARACTER OF THE STATEMENT IS EXAMINED ; 语句的字符被检查
		TO SEE IF IT IS LESS THAN THE RESERVED ; 以查看它是否小于
		WORD TOKEN FOR THE LOWEST NUMBERED STATEMENT NAME. ; 最小编号语句名称的保留字令牌
		IF SO, THE "LET" CODE IS CALLED TO ; 如果是，则调用"LET"代码
		TREAT THE STATEMENT AS AN ASSIGNMENT STATEMENT. ; 将语句视为赋值语句
		OTHERWISE A CHECK IS MADE TO MAKE SURE THE ; 否则进行检查以确保
		RESERVED WORD NUMBER IS NOT TOO LARGE TO BE A ; 保留字号不会太大以至于不能成为
		STATEMENT TYPE NUMBER. IF NOT THE ADDRESS ; 语句类型号。如果不是，则地址
		TO DISPATCH TO IS FETCHED FROM "STMDSP" (THE STATEMENT ; 从"STMDSP"（语句
		DISPATCH LIST) USING THE RESERVED WORD ; 分派列表）获取，使用保留字
		NUMBER FOR THE STATEMENT TO CALCULATE AN INDEX INTO ; 号来计算进入列表的索引
		THE LIST. ; 列表

	ERROR MESSAGES ; 错误消息
		WHEN AN ERROR CONDITION IS DETECTED, ; 当检测到错误条件时
		[ACCX] MUST BE SET UP TO INDICATE WHICH ERROR ; 必须设置[ACCX]以指示哪个错误
		MESSAGE IS APPROPRIATE AND A BRANCH MUST BE MADE ; 消息是合适的，并且必须分支
		TO "ERROR". THE STACK WILL BE RESET AND ALL ; 到"ERROR"。堆栈将被重置，所有
		PROGRAM CONTEXT WILL BE LOST. VARIABLES ; 程序上下文将丢失。变量
		VALUES AND THE ACTUAL PROGRAM REMAIN INTACT. ; 值和实际程序保持完整。
		ONLY THE VALUE OF [ACCX] IS IMPORTANT WHEN ; 只有[ACCX]的值在
		THE BRANCH IS MADE TO ERROR. [ACCX] IS USED AS AN ; 分支到错误时重要。[ACCX]被用作
		INDEX INTO "ERRTAB" WHICH GIVES THE TWO ; 进入"ERRTAB"的索引，该表给出
		CHARACTER ERROR MESSAGE THAT WILL BE PRINTED ON THE ; 两个字符的错误消息，将打印在
		USER'S TERMINAL. ; 用户终端上


	TEXTUAL MESSAGES ; 文本消息
		CONSTANT MESSAGES ARE STORED HERE. UNLESS ; 常量消息存储在这里。除非
		THE CODE TO CHECK IF A STRING MUST BE COPIED ; 检查字符串是否必须复制的代码
		IS CHANGED THESE STRINGS MUST BE STORED ABOVE ; 被更改，否则这些字符串必须存储在
		PAGE ZERO, OR ELSE THEY WILL BE COPIED BEFORE ; 零页之上，否则它们将在
		THEY ARE PRINTED. ; 打印之前被复制

	FNDFOR	; 查找FOR循环
		MOST SMALL ROUTINES ARE FAIRLY SIMPLE ; 大多数小例程相当简单
		AND ARE DOCUMENTED IN PLACE. "FNDFOR" IS ; 并在适当位置有文档。"FNDFOR"是
		USED FOR FINDING "FOR" ENTRIES ON ; 用于查找堆栈上的"FOR"条目
		THE STACK. WHENEVER A "FOR" IS EXECUTED, A ; 每当执行"FOR"时，一个
		16-BYTE ENTRY IS PUSHED ONTO THE STACK. ; 16字节的条目被压入堆栈
		BEFORE THIS IS DONE, HOWEVER, A CHECK ; 然而，在此之前，检查
		MUST BE MADE TO SEE IF THERE ; 必须查看是否有
		ARE ANY "FOR" ENTRIES ALREADY ON THE STACK ; 堆栈上已有任何"FOR"条目
		FOR THE SAME LOOP VARIABLE. IF SO, THAT "FOR" ENTRY ; 用于相同的循环变量。如果是，则该"FOR"条目
		AND ALL OTHER "FOR" ENTRIES THAT WERE MADE AFTER IT ; 以及之后的所有其他"FOR"条目
		ARE ELIMINATED FROM THE STACK. THIS IS SO A ; 从堆栈中消除。这是为了使
		PROGRAM THAT JUMPS OUT OF THE MIDDLE ; 跳出中间的程序
		OF A "FOR" LOOP AND THEN RESTARTS THE LOOP AGAIN ; 的"FOR"循环，然后再次重新启动循环
		AND AGAIN WON'T USE UP 18 BYTES OF STACK ; 不会每次都用完18字节的堆栈
		SPACE EVERY TIME. THE "NEXT" CODE ALSO ; 空间。"NEXT"代码也
		CALLS "FNDFOR" TO SEARCH FOR A "FOR" ENTRY WITH ; 调用"FNDFOR"来搜索具有
		THE LOOP VARIABLE IN ; 循环变量的"FOR"条目
		THE "NEXT". AT WHATEVER POINT A MATCH IS FOUND ; "NEXT"。在任何找到匹配的点
		THE STACK IS RESET. IF NO MATCH IS FOUND A ; 堆栈被重置。如果未找到匹配，则
		"NEXT WITHOUT FOR"  ERROR OCCURS. GOSUB EXECUTION ; 发生"NEXT WITHOUT FOR"错误。GOSUB执行
		ALSO PUTS A 5-BYTE ENTRY ON STACK. ; 也会在堆栈上放置一个5字节的条目
		WHEN A RETURN IS EXECUTED "FNDFOR" IS ; 当执行RETURN时，"FNDFOR"被
		CALLED WITH A VARIABLE POINTER THAT CAN'T ; 调用，带有一个不能
		BE MATCHED. WHEN "FNDFOR" HAS RUN ; 匹配的变量指针。当"FNDFOR"运行
		THROUGH ALL THE "FOR" ENTRIES ON THE STACK  ; 通过堆栈上的所有"FOR"条目后
		IT RETURNS AND THE RETURN CODE MAKES ; 它返回，返回代码确保
		SURE THE ENTRY THAT WAS STOPPED ; 停止的条目
		ON IS A GOSUB ENTRY. THIS ASSURES THAT ; 是GOSUB条目。这确保
		IF YOU GOSUB TO A SECTION OF CODE ; 如果你GOSUB到一段代码
		IN WHICH A FOR LOOP IS ENTERED BUT NEVER ; 其中进入了一个FOR循环但从未
		EXITED THE RETURN WILL STILL BE ; 退出，RETURN仍然能够
		ABLE TO FIND THE MOST RECENT ; 找到最近的
		GOSUB ENTRY. THE "RETURN" CODE ELIMINATES THE ; GOSUB条目。"RETURN"代码消除
		"GOSUB" ENTRY AND ALL "FOR" ENTRIES MADE AFTER ; "GOSUB"条目以及之后的所有"FOR"条目
		THE GOSUB ENTRY. ; GOSUB条目

	NON-RUNTIME STUFF ; 非运行时内容
		THE CODE TO INPUT A LINE, CRUNCH IT, GIVE ERRORS, ; 输入行、压缩它、给出错误的代码
		FIND A SPECIFIC LINE IN THE PROGRAM, ; 在程序中查找特定行
		PERFORM A "NEW", "CLEAR", AND "LIST" ARE ; 执行"NEW"、"CLEAR"和"LIST"都是
		ALL IN THIS AREA. GIVEN THE EXPLANATION OF ; 在这个区域。鉴于
		PROGRAM STORAGE SET FORTH ABOVE, THESE ARE ; 上面阐述的程序存储，这些是
		ALL STRAIGHTFORWARD. ; 全部 straightforward

	NEWSTT ; 新语句
		WHENEVER A STATEMENT FINISHES EXECUTION IT ; 每当语句完成执行时
		DOES A "RTS" WHICH TAKES ; 执行"RTS"，这将
		EXECUTION BACK TO "NEWSTT". STATEMENTS THAT ; 执行返回到"NEWSTT"。创建或查看
		CREATE OR LOOK AT SEMI-PERMANENT STACK ENTRIES ; 半永久堆栈条目的语句
		MUST GET RID OF THE RETURN ADDRESS OF "NEWSTT" AND ; 必须摆脱"NEWSTT"的返回地址并
		JMP TO "NEWSTT" WHEN DONE. "NEWSTT" ALWAYS ; 完成后JMP到"NEWSTT"。"NEWSTT"总是
		CHRGETS THE FIRST CHARACTER AFTER THE STATEMENT ; CHRGET语句名称后的第一个字符
		NAME BEFORE DISPATCHING. WHEN RETURNING ; 在分派之前。当返回
		BACK TO "NEWSTT" THE ONLY THING THAT ; 回到"NEWSTT"时，唯一必须
		MUST BE SET UP IS THE TEXT POINTER IN ; 设置的是"TXTPTR"中的文本指针
		"TXTPTR". "NEWSTT" WILL CHECK TO MAKE SURE ; "NEWSTT"将检查以确保
		"TXTPTR" IS POINTING TO A STATEMENT TERMINATOR. ; "TXTPTR"指向语句终止符
		IF A STATEMENT SHOULDN'T BE PERFORMED UNLESS ; 如果语句不应执行，除非
		IT IS PROPERLY FORMATTED (I.E. "NEW") IT CAN ; 它格式正确（即"NEW"），它可以
		SIMPLY DO A RETURN AFTER READING ALL OF ; 在读取所有参数后简单地执行RETURN
		ITS ARGUMENTS. SINCE THE ZERO FLAG ; 由于零标志
		BEING OFF INDICATES THERE IS NOT ; 关闭表示没有
		A STATEMENT TERMINATOR "NEWSTT" WILL ; 语句终止符，"NEWSTT"将
		DO THE JMP TO THE "SYNTAX ERROR" ; 执行JMP到"SYNTAX ERROR"
		ROUTINE. IF A STATEMENT SHOULD BE STARTED ; 例程。如果语句应该重新启动
		OVER IT CAN DO LDWD OLDTXT, STWD TXTPTR RTS SINCE THE TEXT PNTR ; 它可以执行LDWD OLDTXT, STWD TXTPTR RTS，因为文本指针
		AT "NEWSTT" IS ALWAYS STORED IN "OLDTXT". ; 在"NEWSTT"处总是存储在"OLDTXT"中
		THE ^C CODE STORES [CURLIN] (THE ; ^C代码存储[CURLIN]（
		CURRENT LINE NUMBER) IN "OLDLIN" SINCE THE ^C CHECK ; 当前行号）到"OLDLIN"中，因为^C检查
		IS MADE BEFORE THE STATEMENT POINTED TO IS ; 在指向的语句执行之前进行
		EXECUTED. "STOP" AND "END" STORE THE TEXT POINTER ; 执行。"STOP"和"END"存储文本指针
		FROM "TXTPTR", WHICH POINTS AT THEIR TERMINATING ; 从"TXTPTR"，指向它们的终止
		CHARACTER, IN "OLDTXT". ; 字符，到"OLDTXT"中

	STATEMENT CODE ; 语句代码
		THE INDIVIDUAL STATEMENT CODE COMES ; 各个语句代码
		NEXT. THE APPROACH USED IN EXECUTING EACH ; 接下来。执行每个语句所用的方法
		STATEMENT IS DOCUMENTED IN THE STATEMENT CODE ; 在语句代码本身中有文档记录
		ITSELF. ; 本身

	FRMEVL, THE FORMULA EVALUATOR ; FRMEVL，公式求值器
		GIVEN A TEXT POINTER POINTING TO THE STARTING ; 给定一个指向公式起始字符的文本指针
		CHARACTER OF A FORMULA, "FRMEVL" ; "FRMEVL"
		EVALUATES THE FORMULA AND LEAVES ; 求值公式并将
		THE VALUE IN THE FLOATING ACCUMULATOR (FAC). ; 值留在浮点累加器（FAC）中
		"TXTPTR" IS RETURNED POINTING TO THE FIRST CHARACTER ; "TXTPTR"返回指向第一个
		THAT COULD NOT BE INTERPRETED AS PART OF THE ; 不能解释为公式部分的字符
		FORMULA. THE ALGORITHM USES THE STACK ; 该算法使用堆栈
		TO STORE TEMPORARY RESULTS: ; 来存储临时结果：

			0. PUT A DUMMY PRECEDENCE OF ZERO ON ; 0. 将一个虚拟优先级0放在
				THE STACK. ; 堆栈上
			1. READ LEXEME (CONSTANT,FUNCTION, ; 1. 读取词素（常量、函数、
				VARIABLE,FORMULA IN PARENS) ; 变量、括号中的公式）
				AND TAKE THE LAST PRECEDENCE VALUE ; 并取出堆栈上的最后一个优先级值
				OFF THE STACK. ; 
			2. SEE IF THE NEXT CHARACTER IS AN OPERATOR. ; 2. 查看下一个字符是否是运算符
				IF NOT, CHECK PREVIOUS ONE. THIS MAY CAUSE ; 如果不是，检查前一个。这可能导致
				OPERATOR APPLICATION OR AN ACTUAL ; 运算符应用或实际
				RETURN FROM "FRMEVL". ; 从"FRMEVL"返回
			3. IF IT IS, SEE WHAT PRECEDENCE IT HAS ; 3. 如果是，查看它具有什么优先级
				AND COMPARE IT TO THE PRECEDENCE ; 并将其与堆栈上最后一个运算符的优先级进行比较
				OF THE LAST OPERATOR ON THE STACK. ; 
			4. IF = OR LESS REMEMBER THE OPERATOR ; 4. 如果等于或小于，记住此运算符的
				POINTER OF THIS OPERATOR ; 指针
				AND BRANCH TO "QCHNUM" TO CAUSE ; 并分支到"QCHNUM"以引起
				APPLICATION OF THE LAST OPERATOR. ; 最后一个运算符的应用
				EVENTUALLY RETURN TO STEP 2 ; 最终返回到步骤2
				BY RETURNING TO JUST AFTER "DOPREC". ; 通过返回到"DOPREC"之后
			5. IF GREATER PUT THE LAST PRECEDENCE ; 5. 如果大于，将最后一个优先级
				BACK ON, SAVE THE OPERATOR ADDRESS, ; 放回，保存运算符地址、
				CURRENT TEMPORARY RESULT, ; 当前临时结果
				AND PRECEDENCE AND RETURN TO STEP 1. ; 和优先级，并返回到步骤1

		RELATIONAL OPERATORS ARE ALL HANDLED THROUGH ; 关系运算符都通过
		A COMMON ROUTINE. SPECIAL ; 一个公共例程处理。特别
		CARE IS TAKEN TO DETECT TYPE MISMATCHES SUCH AS 3+"F". ; 注意检测类型不匹配，例如3+"F"

	EVAL -- THE ROUTINE TO READ A LEXEME ; EVAL -- 读取词素的例程
		"EVAL" CHECKS FOR THE DIFFERENT TYPES OF ; "EVAL"检查它应该检测的
		ENTITIES IT IS SUPPOSED TO DETECT. ; 不同类型的实体
		LEADING PLUSES ARE IGNORED, ; 前导加号被忽略
		DIGITS AND "." CAUSE "FIN" (FLOATING INPUT) ; 数字和"."导致"FIN"（浮点输入）
		TO BE CALLED. FUNCTION NAMES CAUSE THE ; 被调用。函数名称导致
		FORMULA INSIDE THE PARENTHESES TO BE EVALUATED ; 括号内的公式被求值
		AND THE FUNCTION ROUTINE TO BE CALLED. VARIABLE ; 并调用函数例程。变量
		NAMES CAUSE "PTRGET" TO BE CALLED TO GET A POINTER ; 名称导致调用"PTRGET"以获取指向值的指针
		TO THE VALUE, AND THEN THE VALUE IS PUT INTO ; 然后将值放入
		THE FAC. AN OPEN PARENTHESIS CAUSES "FRMEVL" ; FAC中。开括号导致"FRMEVL"
		TO BE CALLED (RECURSIVELY), AND THE ")" TO ; 被调用（递归地），并且检查")"
		BE CHECKED FOR. UNARY OPERATORS (NOT AND ; 一元运算符（NOT和
		NEGATION)  PUT THEIR PRECEDENCE ON THE STACK ; 取反）将它们的优先级放在堆栈上
		AND ENTER FORMULA EVALUATION AT STEP 1, SO ; 并在步骤1进入公式求值，因此
		THAT EVERYTHING UP TO AN OPERATOR GREATER THAN ; 直到遇到优先级大于
		THEIR PRECEDENCE OR THE END OF THE FORMULA ; 它们的优先级或公式结束的所有内容
		WILL BE EVALUATED. ; 将被求值

	DIMENSION AND VARIABLE SEARCHING ; 维数和变量搜索
		SPACE IS ALLOCATED FOR VARIABLES AS THEY ARE ; 变量在遇到时分配空间
		ENCOUNTERED. THUS "DIM" STATEMENTS MUST BE ; 因此必须执行"DIM"语句
		EXECUTED TO HAVE EFFECT. 6 BYTES ARE ALLOCATED ; 才能生效。每个简单变量分配6字节
		FOR EACH SIMPLE VARIABLE, WHETHER IT IS A STRING, ; 无论它是字符串、
		NUMBER OR USER DEFINED FUNCTION. THE FIRST TWO ; 数字还是用户定义函数。前两个
		BYTES GIVE THE NAME OF THE VARIABLE AND THE LAST FOUR ; 字节给出变量名称，最后四个
		GIVE ITS VALUE. [VARTAB] GIVES THE FIRST LOCATION ; 给出其值。[VARTAB]给出第一个
		WHERE A SIMPLE VARIABLE NAME IS FOUND AND [ARYTAB] ; 找到简单变量名称的位置，[ARYTAB]
		GIVES THE LOCATION TO STOP SEARCHING FOR SIMPLE ; 给出停止搜索简单变量的位置
		VARIABLES. A "FOR" ENTRY HAS A TEXT POINTER ; 变量。"FOR"条目有一个文本指针
		AND A POINTER TO A VARIABLE VALUE SO NEITHER ; 和一个指向变量值的指针，因此
		THE PROGRAM OR THE SIMPLE VARIABLES CAN BE ; 程序或简单变量都不能
		MOVED WHILE THERE ARE ACTIVE "FOR" ENTRIES ON THE STACK. ; 在堆栈上有活动"FOR"条目时移动
		USER DEFINED FUNCTION VALUES ALSO CONTAIN ; 用户定义函数值也包含
		POINTERS INTO SIMPLE VARIABLE SPACE SO NO USER-DEFINED ; 指向简单变量空间的指针，因此如果简单变量
		FUNCTION VALUES CAN BE RETAINED IF SIMPLE VARIABLES ; 被移动，则不能保留用户定义函数值
		ARE MOVED. ADDING A SIMPLE VARIABLE IS JUST ; 添加一个简单变量只是
		ADDING SIX TO [ARYTAB] AND [STREND], BLOCK TRANSFERING ; 将[ARYTAB]和[STREND]加六，块传输
		THE ARRAY VARIABLES UP BY SIX AND MAKING SURE THE ; 数组变量上移六字节，并确保
		NEW [STREND] IS NOT TOO CLOSE TO THE STRINGS. ; 新的[STREND]不会太接近字符串
		THIS MOVEMENT OF ARRAY VARIABLES MEANS ; 数组变量的这种移动意味着
		THAT NO POINTER TO AN ARRAY WILL STAY VALID WHEN ; 当可能遇到新的简单变量时，指向数组的指针都不会保持有效
		NEW SIMPLE VARIABLES CAN BE ENCOUNTERED. THIS IS ; 这就是为什么
		WHY ARRAY VARIABLES ARE NOT ALLOWED FOR "FOR" ; 数组变量不允许用于"FOR"
		LOOP VARIABLES. SETTING UP A NEW ARRAY VARIABLE ; 循环变量。设置新的数组变量
		MERELY INVOLVES BUILDING THE DESCRIPTOR, ; 仅涉及构建描述符、
		UPDATING [STREND], AND MAKING SURE THERE IS ; 更新[STREND]，并确保
		STILL ENOUGH ROOM BETWEEN [STREND] AND STRING SPACE. ; [STREND]和字符串空间之间仍有足够空间
		"PTRGET", THE ROUTINE WHICH RETURNS A POINTER ; "PTRGET"，返回指向变量值的指针的例程
		TO A VARIABLE VALUE, HAS TWO IMPORTANT FLAGS. ONE IS ; 有两个重要的标志。一个是
		"DIMFLG" WHICH INDICATES WHETHER "DIM" CALLED "PTRGET" ; "DIMFLG"，指示"DIM"是否调用了"PTRGET"
		OR NOT. IF SO, NO PRIOR ENTRY FOR THE VARIABLE IN ; 如果是，则不应找到变量的先前条目
		QUESTION SHOULD BE FOUND, AND THE INDEX INDICATES ; 并且索引指示
		HOW MUCH SPACE TO SET ASIDE. SIMPLE VARIABLES CAN ; 预留多少空间。简单变量可以
		BE "DIMENSIONED", BUT THE ONLY EFFECT WILL BE TO ; 被"维数化"，但唯一效果是
		SET ASIDE SPACE FOR THE VARIABLE IF IT HASN'T BEEN ; 如果变量尚未遇到，则为其预留空间
		ENCOUNTERED YET. THE OTHER IMPORTANT FLAG IS "SUBFLG" ; 另一个重要标志是"SUBFLG"
		WHICH INDICATES WHETHER A SUBSCRIPTED VARIABLE SHOULD BE ; 指示在当前上下文中是否应允许
		ALLOWED IN THE CURRENT CONTEXT. IF [SUBFLG] IS NON-ZERO ; 下标变量。如果[SUBFLG]非零
		THE OPEN PARENTHESIS FOR A SUBSCRIPTED VARIABLE ; 下标变量的开括号
		WILL NOT BE SCANNED BY "PTRGET", AND "PTRGET" WILL RETURN ; 不会被"PTRGET"扫描，并且"PTRGET"将返回
		WITH A TEXT POINTER POINTING TO THE "(", IF ; 文本指针指向"("，如果
		THERE WAS ONE. ; 有一个的话
	STRINGS ; 字符串
		IN THE VARIABLE TABLES STRINGS ARE STORED JUST LIKE ; 在变量表中，字符串的存储方式与
		NUMERIC VARIABLES. SIMPLE STRINGS HAVE THREE VALUE ; 数字变量完全相同。简单字符串有三个值
		BYTES WHICH ARE INITIALIZED TO ALL ZEROS (WHICH ; 字节，初始化为全零（这
		REPRESENTS THE NULL STRING). THE ONLY DIFFERENCE ; 表示空字符串）。唯一区别
		IN HANDLING IS THAT WHEN "PTRGET" SEES A "$" AFTER THE ; 在于当"PTRGET"在变量名称后看到"$"时
		NAME OF A VARIABLE, "PTRGET" SETS [VALTYP] ; "PTRGET"设置[VALTYP]
		TO NEGATIVE ONE AND TURNS ; 为负一并打开
		ON THE MSB (MOST-SIGNIFIGANT-BIT) OF THE VALUE OF ; 变量名称第一个字符值的MSB（最高有效位）
		THE FIRST CHARACTER OF THE VARIABLE NAME. ; 
		HAVING THIS BIT ON IN THE NAME OF THE VARIABLE ENSURES ; 在变量名称中设置此位确保
		THAT THE SEARCH ROUTINE WILL NOT MATCH ; 搜索例程不会将
		'A' WITH 'A$' OR 'A$' WITH 'A'. THE MEANING OF ; 'A'与'A$'或'A$'与'A'匹配。这三个值字节的含义是：
		THE THREE VALUE BYTES ARE: ; 
			LOW ; 低
				LENGTH OF THE STRING ; 字符串长度
				LOW 8 BITS ; 低8位
				HIGH 8 BITS  OF THE ADDRESS ; 地址的高8位
					OF THE CHARACTERS IN THE ; 字符串中字符的地址
					STRING IF LENGTH.NE.0. ; 如果长度不等于0
					MEANINGLESS OTHERWISE. ; 否则无意义
			HIGH ; 高
		THE VALUE OF A STRING VARIABLE (THESE 3 BYTES) ; 字符串变量的值（这3字节）
		IS CALLED THE STRING DESCRIPTOR TO DISTINGUISH ; 称为字符串描述符，以区别于
		IT FROM THE ACTUAL STRING DATA. WHENEVER A ; 实际字符串数据。每当在公式中
		STRING CONSTANT IS ENCOUNTERED IN A FORMULA OR AS ; 或作为输入字符串的一部分遇到字符串常量时
		PART OF AN INPUT STRING, OR AS PART OF DATA, "STRLIT" ; 或作为数据的一部分，"STRLIT"
		IS CALLED, CAUSING A DESCRIPTOR TO BE BUILT FOR ; 被调用，导致为字符串构建描述符
		THE STRING. WHEN ASSIGNMENT IS MADE TO A STRING POINTING INTO ; 当对指向"BUF"的字符串进行赋值时
		"BUF" THE VALUE IS COPIED INTO STRING SPACE SINCE [BUF] ; 值被复制到字符串空间中，因为[BUF]
		IS ALWAYS CHANGING. ; 总是在变化

		STRING FUNCTIONS AND THE ONE STRING OPERATOR "+" ; 字符串函数和字符串运算符"+"
		ALWAYS RETURN THEIR VALUES IN STRING SPACE. ; 总是在字符串空间中返回它们的值
		ASSIGNING A STRING A CONSTANT VALUE IN A PROGRAM ; 在程序中通过"READ"或赋值语句
		THROUGH A "READ" OR ASSIGNMENT STATEMENT ; 为字符串分配常量值
		WILL NOT USE ANY STRING SPACE SINCE ; 不会使用任何字符串空间，因为
		THE STRING DESCRIPTOR  WILL POINT INTO THE ; 字符串描述符将指向
		PROGRAM ITSELF. IN GENERAL, COPYING IS DONE ; 程序本身。通常，复制在以下情况下进行：
		WHEN A STRING VALUE IS IN "BUF", OR IT IS IN STRING ; 当字符串值在"BUF"中，或者在字符串空间中
		SPACE AND THERE IS AN ACTIVE POINTER TO IT. ; 并且有一个指向它的活动指针
		THUS F$=G$ WILL CAUSE COPYING IF G$ HAS ITS ; 因此，如果G$的字符串数据在字符串空间中，则F$=G$将导致复制
		STRING DATA IN STRING SPACE. F$=CHR$(7) ; F$=CHR$(7)
		WILL USE ONE BYTE OF STRING SPACE TO STORE THE ; 将使用一个字节的字符串空间来存储
		NEW ONE CHARACTER STRING CREATED BY "CHR$", BUT ; 由"CHR$"创建的新单字符字符串，但
		THE ASSIGNMENT ITSELF WILL CAUSE NO COPYING SINCE ; 赋值本身不会导致复制，因为
		THE ONLY POINTER AT THE NEW STRING IS A ; 指向新字符串的唯一指针是
		TEMPORARY DESCRIPTOR CREATED BY "FRMEVL" WHICH WILL ; 由"FRMEVL"创建的临时描述符，它将
		GO AWAY AS SOON AS THE ASSIGNMENT IS DONE. ; 在赋值完成后立即消失
		IT IS THE NATURE OF GARBAGE COLLECTION THAT ; 垃圾回收的性质是
		DISALLOWS HAVING TWO STRING DESCRIPTORS POINT TO THE SAME ; 不允许两个字符串描述符指向字符串空间中的同一区域
		AREA IN STRING SPACE. STRING FUNCTIONS AND OPERATORS ; 字符串函数和运算符
		MUST PROCEED AS FOLLOWS: ; 必须按以下步骤进行：
			1) FIGURE OUT THE LENGTH OF THEIR RESULT. ; 1) 计算出它们结果的长度

			2) CALL "GETSPA" TO FIND SPACE FOR THEIR ; 2) 调用"GETSPA"为它们的结果查找空间
			RESULT. THE ARGUMENTS TO THE FUNCTION ; 函数的参数
			OR OPERATOR MAY CHANGE SINCE GARBAGE COLLECTION ; 或运算符可能会改变，因为垃圾回收
			MAY BE INVOKED. THE ONLY THING THAT CAN ; 可能被调用。唯一可以
			BE SAVED DURING THE CALL TO "GETSPA" IS A POINTER ; 在调用"GETSPA"期间保存的是指向参数描述符的指针
			TO THE DESCRIPTORS OF THE ARGUMENTS. ; 
			3) CONSTRUCT THE RESULT DESCRIPTOR IN "DSCTMP". ; 3) 在"DSCTMP"中构建结果描述符
			"GETSPA" RETURNS THE LOCATION OF THE AVAILABLE ; "GETSPA"返回可用空间的位置
			SPACE. ; 
			4) CREATE THE NEW VALUE BY COPYING PARTS ; 4) 通过复制参数的部分或其他内容来创建新值
			OF THE ARGUMENTS OR WHATEVER. ; 
			5) FREE UP THE ARGUMENTS BY CALLING "FRETMP". ; 5) 通过调用"FRETMP"释放参数
			6) JUMP TO "PUTNEW" TO GET THE DESCRIPTOR IN ; 6) 跳转到"PUTNEW"以将"DSCTMP"中的描述符
			"DSCTMP" TRANSFERRED INTO A NEW STRING TEMPORARY. ; 传输到新的字符串临时变量中

		THE REASON FOR STRING TEMPORARIES IS THAT GARBAGE ; 字符串临时变量的原因是垃圾回收
		COLLECTION HAS TO KNOW ABOUT ALL ACTIVE STRING DESCRIPTORS ; 必须知道所有活动字符串描述符
		SO IT KNOWS WHAT IS AND ISN'T IN USE. STRING TEMPORARIES ARE ; 以便知道什么在使用中，什么不在使用中。字符串临时变量
		USED TO STORE THE DESCRIPTORS OF STRING EXPRESSIONS. ; 用于存储字符串表达式的描述符
		
		INSTEAD OF HAVING AN ACTUAL VALUE STORED IN THE ; 与将实际值存储在FAC中不同
		FAC, AND HAVING THE VALUE OF A TEMPORARY RESULT ; 并且将临时结果的值
		BEING SAVED ON THE STACK, AS HAPPENS WITH NUMERIC ; 保存在堆栈上（如数字变量那样）不同
		VARIABLES, STRINGS HAVE THE POINTER TO A STRING DESCRIPTOR ; 字符串将指向字符串描述符的指针存储在FAC中
		STORED IN THE FAC, AND IT IS THIS POINTER ; 并且正是这个指针
		THAT GETS SAVED ON THE STACK BY FORMULA EVALUATION. ; 被公式求值保存在堆栈上
		STRING FUNCTIONS CANNOT FREE THEIR ARGUMENTS UP RIGHT ; 字符串函数不能立即释放它们的参数
		AWAY SINCE "GETSPA" MAY FORCE ; 因为"GETSPA"可能强制
		GARBAGE COLLECTION AND THE ARGUMENT STRINGS ; 垃圾回收，并且参数字符串
		MAY BE OVER-WRITTEN SINCE GARBAGE COLLECTION ; 可能被覆盖，因为垃圾回收
		WILL NOT BE ABLE TO FIND AN ACTIVE POINTER TO ; 将无法找到指向它们的活动指针
		THEM. FUNCTION AND OPERATOR RESULTS ARE BUILT IN ; 函数和运算符结果构建在
		"DSCTMP" SINCE STRING TEMPORARIES ARE ALLOCATED ; "DSCTMP"中，因为字符串临时变量以FIFO顺序
		(PUTNEW) AND DEALLOCATED (FRETMP) IN A FIFO ORDERING ; 分配（PUTNEW）和释放（FRETMP）
		(I.E. A STACK) SO THE NEW TEMPORARY CANNOT ; （即堆栈），因此新的临时变量不能
		BE SET UP UNTIL THE OLD ONE(S) ARE FREED. TRYING ; 在旧的临时变量释放之前设置。尝试
		TO BUILD A RESULT IN A TEMPORARY AFTER ; 在释放参数临时变量之后在临时变量中构建结果
		FREEING UP THE ARGUMENT TEMPORARIES COULD RESULT ; 可能导致一个参数临时变量被新结果过早覆盖
		IN ONE OF THE ARGUMENT TEMPORARIES BEING OVERWRITTEN ; 
		TOO SOON BY THE NEW RESULT. ; 

		STRING SPACE IS ALLOCATED AT THE VERY TOP ; 字符串空间分配在内存的最顶部
		OF MEMORY. "MEMSIZ" POINTS BEYOND THE LAST LOCATION OF ; "MEMSIZ"指向字符串空间最后一个位置之后
		STRING SPACE. STRINGS ARE STORED IN HIGH LOCATIONS ; 字符串存储在高地址
		FIRST. WHENEVER STRING SPACE IS ALLOCATED (GETSPA). ; 首先。每当分配字符串空间时（GETSPA）
		[FRETOP], WHICH IS INITIALIZED TO [MEMSIZ], IS UPDATED ; [FRETOP]初始化为[MEMSIZ]，被更新
		TO GIVE THE HIGHEST LOCATION IN STRING SPACE ; 以给出字符串空间中未使用的最高位置
		THAT IS NOT IN USE. THE RESULT IS THAT ; 结果是
		[FRETOP] GETS SMALLER AND SMALLER, UNTIL SOME ; [FRETOP]变得越来越小，直到某个
		ALLOCATION WOULD MAKE [FRETOP] LESS THAN OR EQUAL TO ; 分配会使[FRETOP]小于或等于
		[STREND]. THIS MEANS STRING SPACE HAS RUN INTO THE ; [STREND]。这意味着字符串空间已经碰到了
		THE ARRAYS AND THAT GARBAGE COLLECTION MUST BE CALLED. ; 数组，必须调用垃圾回收

		GARBAGE COLLECTION: ; 垃圾回收：
			0. [MINPTR]=[STREND] [FRETOP]=[MEMSIZ] ; 0. [MINPTR]=[STREND] [FRETOP]=[MEMSIZ]
			1. [REMMIN]=0 ; 1. [REMMIN]=0
			2. FOR EACH STRING DESCRIPTOR ; 2. 对于每个字符串描述符
			(TEMPORARIES, SIMPLE STRINGS, STRING ARRAYS) ; （临时变量、简单字符串、字符串数组）
			IF THE STRING IS NOT NULL AND ITS POINTER IS ; 如果字符串不为空且其指针
			.GT.MINPTR AND .LT.FRETOP, ; 大于MINPTR且小于FRETOP
			[MINPTR]=THIS STRING DESCRIPTOR'S POINTER, ; [MINPTR]=此字符串描述符的指针
			[REMMIN]=POINTER AT THIS STRING DESCRIPTOR. ; [REMMIN]=指向此字符串描述符的指针
			END. ; 结束
			3. IF REMMIN.NE.0 (WE FOUND AN UNCOLLECTED STRING), ; 3. 如果REMMIN不等于0（我们找到了一个未回收的字符串）
			BLOCK TRANSFER THE STRING DATA POINTED ; 块传输由"REMMIN"指向的字符串描述符所指向的字符串数据
			TO IN THE STRING DESCRIPTOR POINTED TO BY "REMMIN" ; 
			SO THAT THE LAST BYTE OF STRING DATA IS AT ; 使得字符串数据的最后一个字节在
			[FRETOP]. UPDATE [FRETOP] SO THAT IT ; [FRETOP]处。更新[FRETOP]使得它
			POINTS TO THE LOCATION JUST BELOW THE ONE ; 指向字符串数据移动到的位置之下的位置
			THE STRING DATA WAS MOVED INTO. UPDATE ; 更新
			THE POINTER IN THE DESCRIPTOR SO IT POINTS ; 描述符中的指针，使其指向
			TO THE NEW LOCATION OF THE STRING DATA. ; 字符串数据的新位置
			GO TO STEP 1. ; 转到步骤1

		AFTER CALLING GARBAGE COLLECTION "GETSPA" AGAIN CHECKS ; 调用垃圾回收后，"GETSPA"再次检查
		TO SEE IF [ACCA] CHARACTERS ARE AVAILABLE BETWEEN ; [ACCA]个字符是否在[STREND]和[FRETOP]之间可用
		[STREND] AND [FRETOP]; IF NOT, AN "OUT OF STRING" ; 如果不可用，则引发"OUT OF STRING"
		ERROR IS INVOKED. ; 错误

	MATH PACKAGE ; 数学包
		THE MATH PACKAGE CONTAINS FLOATING INPUT (FIN), ; 数学包包含浮点输入（FIN）
		FLOATING OUTPUT (FOUT), FLOATING COMPARE (FCOMP) ; 浮点输出（FOUT）、浮点比较（FCOMP）
		... AND ALL THE NUMERIC OPERATORS AND FUNCTIONS. ; ...以及所有数值运算符和函数
		THE FORMATS, CONVENTIONS AND ENTRY POINTS ARE ALL ; 格式、约定和入口点都在
		DESCRIBED IN THE MATH PACKAGE ITSELF. ; 数学包本身中有描述

	INIT -- THE INITIALIZATION ROUTINE ; INIT -- 初始化例程
		THE AMOUNT OF MEMORY, ; 内存量、
		TERMINAL WIDTH, AND WHICH FUNCTIONS TO BE RETAINED ; 终端宽度以及要保留哪些函数
		ARE ASCERTAINED FROM THE USER. A ZERO IS PUT DOWN ; 从用户那里确定。一个零被放在
		AT THE FIRST LOCATION NOT USED BY THE MATH-PACKAGE ; 数学包未使用的第一个位置
		AND [TXTTAB] IS SET UP TO POINT AT THE NEXT LOCATION. ; 并且[TXTTAB]被设置为指向下一个位置
		THIS DETERMINES WHERE PROGRAM STORAGE WILL START. ; 这决定了程序存储将从哪里开始
		SPECIAL CHECKS ARE MADE TO MAKE SURE ; 进行特殊检查以确保
		ALL QUESTIONS IN "INIT" ARE ANSWERED REASONABLY, SINCE ; "INIT"中的所有问题都得到合理回答，因为
		ONCE "INIT" FINISHES, THE LOCATIONS IT USES ARE ; 一旦"INIT"完成，它使用的位置将被
		USED FOR PROGRAM STORAGE. THE LAST THING "INIT" DOES IS ; 用于程序存储。"INIT"做的最后一件事是
		CHANGE LOCATION ZERO TO BE A JUMP TO "READY" INSTEAD ; 将位置零更改为跳转到"READY"而不是
		OF "INIT". ONCE THIS IS DONE THERE IS NO WAY TO RESTART ; "INIT"。一旦完成，就无法重新启动
		"INIT". ; "INIT"
HIGH LOCATIONS ; 高地址

* ; 注释块结束
PAGE
SUBTTL	PAGE ZERO. ; 子标题：零页
IFN	REALIO-3,< ; 如果REALIO不等于3
START:	JMP	INIT		;INITIALIZE - SETUP CERTAIN LOCATIONS ; 初始化 - 设置某些位置
				;AND DELETE FUNCTIONS IF NOT NEEDED, ; 并删除不需要的函数
				;AND CHANGE THIS TO "JMP READY" ; 并将此更改为"JMP READY"
				;IN CASE USER RESTARTS AT LOC ZERO. ; 以防用户在位置零重新启动
RDYJSR: JMP	INIT		;CHANGED TO "JMP STROUT" BY "INIT" ; 由"INIT"更改为"JMP STROUT"
				;TO HANDLE ERRORS. ; 用于处理错误
ADRAYI: ADR(AYINT)		;STORE HERE THE ADDR OF THE ; 在此存储将FAC转换为两字节有符号整数的例程地址
				;ROUTINE TO TURN THE FAC INTO A ; 
				;TWO BYTE SIGNED INTEGER IN [Y,A] ; 到[Y,A]中的例程地址
ADRGAY: ADR(GIVAYF)>		;STORE HERE THE ADDR OF THE ; 在此存储将[Y,A]转换为浮点数的例程地址
				;ROUTINE TO CONVERT [Y,A] TO A FLOATING ; 
				;POINT NUMBER IN THE FAC. ; 到FAC中的例程地址
IFN	ROMSW,< ; 如果ROMSW非零
USRPOK: JMP	FCERR>		;SET UP ORIG BY INIT. ; 由INIT设置原始值
;
;
; 这是“易变”存储区域，其中任何内容都不能保存在ROM中。
; 此区域中的任何常量都不能保存在ROM中，而必须由ROM中的程序指令加载。
;
;
; --- 通用RAM ---:
CHARAC: BLOCK	1		;分隔字符。
INTEGR= CHARAC			;来自"QINT"的单字节整数。
ENDCHR: BLOCK	1		;另一个分隔字符。
COUNT:	BLOCK	1		;通用计数器。

; --- 标志 ---:
DIMFLG: BLOCK	1		;在获取变量指针时，记住是否因"DIM"而进行很重要。
				;DIMFLG和VALTYP必须是连续位置。
                ;
                ;
                ;
KIMY=	DIMFLG			;在OUT期间保留Y的位置。
VALTYP: BLOCK	1		;类型指示器。
				;0=数值 1=字符串。
IFN	INTPRC,<
INTFLG: BLOCK	1>		;指示是否为整数。
DORES:	BLOCK	1		;是否能够或不能压缩保留字。
				;当"DATA"被CRUNCH扫描时打开，因此未引用的字符串不会被压缩。
                ;
                ;
GARBFL= DORES			;是否进行垃圾回收。
SUBFLG: BLOCK	1		;标志是否允许下标变量。
				;"FOR"和用户定义函数指针获取在调用"PTRGET"之前打开此标志，
				;以便不会检测到数组。
				;"STKINI"和"PTRGET"清除它。
				;同时在那里不允许整数。
                ;
                ;
INPFLG: BLOCK	1		;标志我们是在执行"INPUT"还是"READ"。
                ;
TANSGN: BLOCK	1		;用于确定正切符号。
IFN	REALIO,<
CNTWFL: BLOCK	1>		;抑制输出标志。
				;非零表示抑制。
				;由"INPUT"、READY和错误重置。
				;由输入^O取反。

IFE	REALIO-4,<ORG	80>	;为APPLE第0页内容留出空间。
; --- 处理终端的RAM ---:
IFN	EXTIO,<
CHANNL: BLOCK	1>		;保存通道号。
IFN	NULCMD,<
NULCNT: 0>			;要打印的空字符数。
IFN	REALIO-3,<
TRMPOS: BLOCK	1>		;终端 carriage 的位置。
LINWID: LINLEN			;行长度（宽度）。
NCMWID: NCMPOS			;超出此位置后没有更多字段。
                ;
LINNUM: 0			;在BUF之前存储行号的位置，
				;以便"BLTUC"可以一次性存储所有内容。
	44			;逗号（预加载或来自ROM）
				;由INPUT语句使用，因为数据指针总是以逗号或终止符开始。
                ;
                ;
IFE	BUFPAG,<
BUF:	BLOCK	BUFLEN>		;键入的内容存储在这里。
				;直接语句从这里执行。记住"INPUT"会破坏BUF。
				;必须在第0页，否则直接语句中的字符串值赋值不会复制到字符串空间——这是必须的。
				;注意：两个非零字节必须位于"BUFLNM"之前。
                ;
                ;
                ;
                ;

; --- 临时事物存储 ---:
TEMPPT: BLOCK	1		;指向第一个空闲临时描述符的指针。
				;初始化为指向TEMPST。
LASTPT: BLOCK	2		;指向最后使用的字符串临时的指针。
TEMPST: BLOCK	STRSIZ*NUMTMP	;NUMTMP临时描述符的存储空间。
INDEX1: BLOCK	2		;索引。
INDEX=	INDEX1
INDEX2: BLOCK	2
RESHO:	BLOCK	1		;乘法和除法的结果。
IFN	ADDPRC,<
RESMOH: BLOCK	1>		;再多一个字节。
RESMO:	BLOCK	1
RESLO:	BLOCK	1
ADDEND= RESMO			;由"UMULT"使用的临时变量。
	0			;RES的溢出。

; --- 指向动态数据结构的指针 ---;
TXTTAB: BLOCK	2		;指向文本开始的指针。
				;在由"INIT"设置后不会更改。
                ;
VARTAB: BLOCK	2		;指向简单变量空间开始的指针。
				;每当程序大小更改时更新，由"SCRATCH"（"NEW"）设置为[TXTTAB]。
                ;
                ;
                ;
ARYTAB: BLOCK	2		;指向数组表开始的指针。
				;每当找到新的简单变量时增加6，并由"CLEARC"设置为[VARTAB]。
                ;
                ;
                ;
STREND: BLOCK	2		;使用中的存储结束。
				;每当遇到新数组或简单变量时增加。
				;由"CLEARC"设置为[VARTAB]。
                ;
FRETOP: BLOCK	2		;字符串空闲空间的顶部。
FRESPC: BLOCK	2		;指向新字符串的指针。
MEMSIZ: BLOCK	2		;内存中的最高位置。

; --- 行号和文本指针 ---:
CURLIN: BLOCK	2		;当前行号。
				;对于直接语句设置为0,255。
OLDLIN: BLOCK	2		;旧行号（由^C、"STOP"或程序中的"END"设置）。
                ;
POKER=	LINNUM			;设置POKE使用的位置。
				;INPUT和READ代码的临时变量
OLDTXT: BLOCK	2		;旧文本指针。
				;指向下一个要执行的语句。
DATLIN: BLOCK	2		;数据行号——为错误记住。
DATPTR: BLOCK	2		;指向数据的指针。由"RESTORE"（由"CLEARC"调用）初始化为指向[TXTTAB]前面的零。
				;由执行"READ"更新。
                ;
                ;
INPPTR: BLOCK	2		;记住INPUT来自哪里。

; --- 求值中使用的东西 ---:
VARNAM: BLOCK	2		;变量名存储在这里。
VARPNT: BLOCK	2		;指向内存中变量的指针。
FDECPT= VARPNT			;指向"FOUT"的十的幂的指针。
FORPNT: BLOCK	2		;用于"FOR"循环和"LET"语句的变量指针。
                ;
LSTPNT= FORPNT			;指向列表字符串的指针。
ANDMSK= FORPNT			;WAIT用于AND操作的掩码。
EORMSK= FORPNT+1		;WAIT中用于EOR操作的掩码。
OPPTR:	BLOCK	2		;指向"OPTAB"中当前操作符条目的指针。
VARTXT= OPPTR			;指向变量列表的指针。
OPMASK: BLOCK	1		;由当前操作符创建的掩码。
DOMASK=TANSGN			;关系操作中使用的掩码。
DEFPNT: BLOCK	2		;函数定义中使用的指针。
GRBPNT= DEFPNT			;垃圾收集中使用的另一个指针。
DSCPNT: BLOCK	2		;指向字符串描述符的指针。
IFN	ADDPRC,<BLOCK	1>	;用于TEMPF3。
FOUR6:	EXP	STRSIZ		;垃圾收集中使用的变量常量。

; --- 其他 ---:
JMPER:	JMP	60000
SIZE=	JMPER+1
OLDOV=	JMPER+2			;旧溢出。
TEMPF3= DEFPNT			;第三个FAC临时变量（4字节）。
TEMPF1:
IFN	ADDPRC,<0>		;用于TEMPF1的额外字节。
HIGHDS: BLOCK	2		;BLT中最高元素的目标。
HIGHTR: BLOCK	2		;要移动的最高元素的源。
TEMPF2:
IFN	ADDPRC,<0>		;用于TEMPF2的额外字节。
LOWDS:	BLOCK	2		;最后一个传输字节的位置。
LOWTR:	BLOCK	2		;BLT中最后要移动的东西。
ARYPNT= HIGHDS			;数组构建中使用的指针。
GRBTOP= LOWTR			;垃圾收集中使用的指针。
DECCNT= LOWDS			;小数点前的位数。
TENEXP= LOWDS+1			;是否输入了小数点？
DPTFLG= LOWTR			;以十为底的指数。
EXPSGN= LOWTR+1			;以十为底的指数的符号。

; --- 浮点累加器 ---:
FAC:
FACEXP: 0
FACHO:	0			;尾数的最高有效字节。
IFN	ADDPRC,<
FACMOH: 0>			;再多一个。
FACMO:	0			;尾数的中间顺序。
FACLO:	0			;尾数的最低有效字节。
FACSGN: 0			;FAC的符号（0或-1）（当未打包时）。
SGNFLG: 0			;FAC的符号由"FIN"保留在这里。
DEGREE= SGNFLG			;多项式使用的计数。
DSCTMP= FAC			;临时描述符构建在这里。
INDICE= FACMO			;由"QINT"设置索引在这里。
BITS:	0			;供"SHIFTR"使用的东西。

; --- 浮点参数（未打包）---:
ARGEXP: 0
ARGHO:	0
IFN	ADDPRC,<ARGMOH: 0>
ARGMO:	0
ARGLO:	0
ARGSGN: 0

ARISGN: 0			;反映结果的符号。
FACOV:	0			;FAC的溢出字节。
STRNG1= ARISGN			;指向字符串或描述符的指针。

FBUFPT: BLOCK	2		;指向FOUT使用的FBUFFR的指针。
BUFPTR= FBUFPT			;指向"CRUNCH"使用的BUF的指针。
STRNG2= FBUFPT			;指向字符串或描述符的指针。
POLYPT= FBUFPT			;指向多项式系数的指针。
CURTOL= FBUFPT			;绝对线性索引在这里形成。
PAGE
SUBTTL	RAM代码。
; 这段代码在整个执行过程中会被更改。
; 通过这种方式使其快速。
; 此外，[X]和[Y]不会被干扰。
;
; "CHRGET"使用[TXTPTR]作为当前文本指针，
; 在递增[TXTPTR]后获取新字符到ACCA中，
; 并根据ACCA中的内容设置条件码。
;	NOT C=	数字	  ("0" 到 "9")
;	Z=	":" 或行结束（空字符）
;
; [ACCA] = 新字符。
; [TXTPTR]=[TXTPTR]+1
;
; 如果存在ROM，则以下内容存在于ROM中，并由INIT加载到这里。
; 否则，它就像所有其他RAM一样加载到此RAM中。
;
;
CHRGET: INC	CHRGET+7	;递增整个TXTPTR。
	BNE	CHRGOT
	INC	CHRGET+8
CHRGOT: LDA	60000		;带有扩展地址的加载。
TXTPTR= CHRGOT+1
	CMPI	" "		;跳过空格。
	BEQ	CHRGET
QNUM:	CMPI	":"		;是":"吗？
	BCS	CHRRTS		;大于等于":"。
	SEC
	SBCI	"0"		;所有大于"9"的字符都已返回，所以
	SEC
	SBCI	256-"0"		;检查是否为数字。
				;如果是数字，则打开进位。
				;同时，如果为空则设置Z。
CHRRTS: RTS			;返回调用者。

RNDX:	128			;加载或来自ROM。
	79			;初始随机数。
	199
	82
IFN	ADDPRC,<89>		;再多一个字节。

ORG	255			;第1页内容即将到来。
LOFBUF: BLOCK	1		;低FAC缓冲区。可复制。
;--- 第0页/第1页边界 ---。
				;必须有13个连续字节。
FBUFFR: BLOCK	3*ADDPRC+13	;"FOUT"的缓冲区。
				;在第1页，因此字符串不会被复制。

;堆栈位于此处。即从FBUFFR结束到STKEND。
PAGE
SUBTTL	DISPATCH TABLES, RESERVED WORDS, AND ERROR TEXTS.   ;分派表、保留字和错误文本。

	ORG	ROMLOC

STMDSP: ADR(END-1)
	ADR(FOR-1)
	ADR(NEXT-1)
	ADR(DATA-1)
IFN	EXTIO,<
	ADR(INPUTN-1)>
	ADR(INPUT-1)
	ADR(DIM-1)
	ADR(READ-1)
	ADR(LET-1)
	ADR(GOTO-1)
	ADR(RUN-1)
	ADR(IF-1)
	ADR(RESTORE-1)
	ADR(GOSUB-1)
	ADR(RETURN-1)
	ADR(REM-1)
	ADR(STOP-1)
	ADR(ONGOTO-1)
IFN	NULCMD,<
	ADR(NULL-1)>
	ADR(FNWAIT-1)
IFN	DISKO,<
IFE	REALIO-3,<
	ADR(CQLOAD-1)
	ADR(CQSAVE-1)
	ADR(CQVERF-1)>
IFN	REALIO,<
IFN	REALIO-2,<
IFN	REALIO-3,<
IFN	REALIO-5,<
	ADR(LOAD-1)
	ADR(SAVE-1)>>>>
IFN	REALIO-1,<
IFN	REALIO-3,<
IFN	REALIO-4,<
	ADR(511)		;LOAD的地址
	ADR(511)>>>>		;SAVE的地址
	ADR(DEF-1)
	ADR(POKE-1)
IFN	EXTIO,<
	ADR(PRINTN-1)>
	ADR(PRINT-1)
	ADR(CONT-1)
IFE	REALIO,<
	ADR(DDT-1)>
	ADR(LIST-1)
	ADR(CLEAR-1)
IFN	EXTIO,<
	ADR(CMD-1)
	ADR(CQSYS-1)
	ADR(CQOPEN-1)
	ADR(CQCLOS-1)>
IFN	GETCMD,<
	ADR(GET-1)>		;用GET地址填充。
	ADR(SCRATH-1)

FUNDSP: ADR(SGN)
	ADR(INT)
	ADR(ABS)
IFE	ROMSW,<
USRLOC: ADR(FCERR)>		;最初没有用户例程。
IFN	ROMSW,<
USRLOC: ADR(USRPOK)>
	ADR(FRE)
	ADR(POS)
	ADR(SQR)
	ADR(RND)
	ADR(LOG)
	ADR(EXP)
IFN	KIMROM,<
REPEAT	4,<
	ADR(FCERR)>>
IFE	KIMROM,<
COSFIX: ADR(COS)
SINFIX: ADR(SIN)
TANFIX: ADR(TAN)
ATNFIX: ADR(ATN)>
	ADR(PEEK)
	ADR(LEN)
	ADR(STR)
	ADR(VAL)
	ADR(ASC)
	ADR(CHR)
	ADR(LEFT)
	ADR(RIGHT)
	ADR(MID)
OPTAB:	121
	ADR(FADDT-1)
	121
	ADR(FSUBT-1)
	123
	ADR(FMULTT-1)
	123
	ADR(FDIVT-1)
	127
	ADR(FPWRT-1)
	80
	ADR(ANDOP-1)
	70
	ADR(OROP-1)
NEGTAB: 125
	ADR(NEGOP-1)
NOTTAB: 90
	ADR(NOTOP-1)
PTDORL: 100			;优先级。
	ADR	(DOREL-1)	;操作符地址。
;
; 保留字的令牌总是设置最高位。
; 保留字列表：
;
Q=128-1
DEFINE	DCI(A),<Q=Q+1
	DC(A)>
RESLST: DCI"END"
	ENDTK==Q
	DCI"FOR"
	FORTK==Q
	DCI"NEXT"
	DCI"DATA"
	DATATK==Q
IFN	EXTIO,<
	DCI"INPUT#">
	DCI"INPUT"
	DCI"DIM"
	DCI"READ"
	DCI"LET"
	DCI"GOTO"
	GOTOTK==Q
	DCI"RUN"
	DCI"IF"
	DCI"RESTORE"
	DCI"GOSUB"
	GOSUTK=Q
	DCI"RETURN"
	DCI"REM"
	REMTK=Q
	DCI"STOP"
	DCI"ON"
IFN	NULCMD,<
	DCI"NULL">
	DCI"WAIT"
IFN	DISKO,<
	DCI"LOAD"
	DCI"SAVE"
IFE	REALIO-3,<
	DCI"VERIFY">>
	DCI"DEF"
	DCI"POKE"
IFN	EXTIO,<
	DCI"PRINT#">
	DCI"PRINT"
	PRINTK==Q
	DCI"CONT"
IFE	REALIO,<
	DCI"DDT">
	DCI"LIST"
IFN	REALIO-3,<
	DCI"CLEAR">
IFE	REALIO-3,<
	DCI"CLR">
IFN	EXTIO,<
	DCI"CMD"
	DCI"SYS"
	DCI"OPEN"
	DCI"CLOSE">
IFN	GETCMD,<
	DCI"GET">
	DCI"NEW"
	SCRATK=Q
; 命令列表结束。
	"T"
	"A"
	"B"
	"("+128
	Q=Q+1
	TABTK=Q
	DCI"TO"
	TOTK==Q
	DCI"FN"
	FNTK==Q
	"S"
	"P"
	"C"
	"("+128			;宏不喜欢参数中的('s。
	Q=Q+1
	SPCTK==Q
	DCI"THEN"
	THENTK=Q
	DCI"NOT"
	NOTTK==Q
	DCI"STEP"
	STEPTK=Q
	DCI"+"
	PLUSTK=Q
	DCI"-"
	MINUTK=Q
	DCI"*"
	DCI"/"
	DCI"^"
	DCI"AND"
	DCI"OR"
	190			;大于号
	Q=Q+1
	GREATK=Q
	DCI"="
	EQULTK=Q
	188
	Q=Q+1			;小于号
	LESSTK=Q
;
;
; 注意一个保留字是另一个保留字的一部分的危险：
; 例如：IF 2 GREATER THAN F OR T=5 THEN...
; 将无法工作！！！因为"FOR"将被压缩！！
; 在任何情况下，确保较小的单词出现在保留字表的后面（"INP"和"INPUT"）
; 另一个例子：IF T OR Q THEN ... "TO"被压缩
;
;
;
	DCI"SGN"
	ONEFUN=Q
	DCI"INT"
	DCI"ABS"
	DCI"USR"
	DCI"FRE"
	DCI"POS"
	DCI"SQR"
	DCI"RND"
	DCI"LOG"
	DCI"EXP"
	DCI"COS"
	DCI"SIN"
	DCI"TAN"
	DCI"ATN"
	DCI"PEEK"
	DCI"LEN"
	DCI"STR$"
	DCI"VAL"
	DCI"ASC"
	DCI"CHR$"
LASNUM==Q			;最后一个接受一个参数的函数的编号
				;
	DCI"LEFT$"
	DCI"RIGHT$"
	DCI"MID$"
	DCI"GO"
GOTK==Q
	0			;标记保留字列表结束

IFE LNGERR,<
Q=0-2
DEFINE	DCE(X),<Q=Q+2
	DC(X)>
ERRTAB: DCE"NF"
	ERRNF==Q		;NEXT WITHOUT FOR。
	DCE"SN"
	ERRSN==Q		;语法错误。
	DCE"RG"
	ERRRG==Q		;RETURN WITHOUT GOSUB。
	DCE"OD"
	ERROD==Q		;数据不足。
	DCE"FC"
	ERRFC==Q		;非法数量。
	DCE"OV"
	ERROV==Q		;溢出。
	DCE"OM"
	ERROM==Q		;内存不足。
	DCE"US"
	ERRUS==Q		;未定义语句。
	DCE"BS"
	ERRBS==Q		;错误下标。
	DCE"DD"
	ERRDD==Q		;重新定维数组。
	DCE"/0"
	ERRDV0==Q		;除以零。
	DCE"ID"
	ERRID==Q		;非法直接命令。
	DCE"TM"
	ERRTM==Q		;类型不匹配。
	DCE"LS"
	ERRLS==Q		;字符串过长。
IFN	EXTIO,<
	DCE"FD"			;文件数据。
	ERRBD==Q>
	DCE"ST"
	ERRST==Q		;字符串公式太复杂。
	DCE"CN"
	ERRCN==Q		;无法继续。
	DCE"UF"
	ERRUF==Q>		;未定义函数。

IFN LNGERR,<
Q=0
; 注意：如果错误消息超过256个字符，此错误计数技术将无效
;
ERRTAB: DC"NEXT WITHOUT FOR"
	ERRNF==Q
	Q=Q+16
	DC"SYNTAX"
	ERRSN==Q
	Q=Q+6
	DC"RETURN WITHOUT GOSUB"
	ERRRG==Q
	Q=Q+20
	DC"OUT OF DATA"
	ERROD==Q
	Q=Q+11
	DC"ILLEGAL QUANTITY"
	ERRFC==Q
	Q=Q+16
	DC"OVERFLOW"
	ERROV==Q
	Q=Q+8
	DC"OUT OF MEMORY"
	ERROM==Q
	Q=Q+13
	DC"UNDEF'D STATEMENT"
	ERRUS==Q
	Q=Q+17
	DC"BAD SUBSCRIPT"
	ERRBS==Q
	Q=Q+13
	DC"REDIM'D ARRAY"
	ERRDD==Q
	Q=Q+13
	DC"DIVISION BY ZERO"
	ERRDV0==Q
	Q=Q+16
	DC"ILLEGAL DIRECT"
	ERRID==Q
	Q=Q+14
	DC"TYPE MISMATCH"
	ERRTM==Q
	Q=Q+13
	DC"STRING TOO LONG"
	ERRLS==Q
	Q=Q+15
IFN	EXTIO,<
	DC"FILE DATA"
	ERRBD==Q
	Q=Q+9>
	DC"FORMULA TOO COMPLEX"
	ERRST==Q
	Q=Q+19
	DC"CAN'T CONTINUE"
	ERRCN==Q
	Q=Q+14
	DC"UNDEF'D FUNCTION"
	ERRUF==Q>

;
; 所有版本中都需要消息。
;
ERR:	DT" ERROR"
	0
INTXT:	DT" IN "
	0
REDDY:	ACRLF
IFE REALIO-3,<
	DT"READY.">
IFN REALIO-3,<
	DT"OK">
	ACRLF
	0
BRKTXT: ACRLF
	DT"BREAK"
	0
PAGE
SUBTTL	GENERAL STORAGE MANAGEMENT ROUTINES.    ;通用存储管理例程。
;
; 通过"VARPNT"在堆栈上查找"FOR"条目。
;
FORSIZ==2*ADDPRC+16
FNDFOR: TSX			;将X寄存器加载为堆栈指针。
	REPEAT	4,<INX>		;忽略ADR(NEWSTT)和RTS地址。
FFLOOP: LDA	257,X		;获取堆栈条目。
	CMPI	FORTK		;是"FOR"令牌吗？
	BNE	FFRTS		;否，没有带有此指针的"FOR"循环。
	LDA	FORPNT+1	;获取高位。
	BNE	CMPFOR
	LDA	258,X		;指针为零，因此假定是这个。
	STA	FORPNT
	LDA	259,X
	STA	FORPNT+1
CMPFOR: CMP	259,X
	BNE	ADDFRS		;不是这个。
	LDA	FORPNT		;获取低位。
	CMP	258,X
	BEQ	FFRTS		;找到了！找到了！
ADDFRS: TXA
	CLC			;向X添加16。
	ADCI	FORSIZ
	TAX			;结果放回X。
	BNE	FFLOOP
FFRTS:	RTS			;返回调用者。

;
; 这是块传输例程。
; 它通过向前推所有内容来腾出空间。
;
; 进入时：
; [Y,A]=[HIGHDS]    （出于原因）。
; [HIGHDS]= [高地址]的目标。
; [LOWTR]= 要传输的最低地址。
; [HIGHTR]= 要传输的最高地址。
;
; 进行检查以确保字符串空间底部与传输到的最高位置之间留有合理的空间。
;
;
;
; 退出时：
; [LOWTR] 未更改。
; [HIGHTR]=[LOWTR]-200 八进制。
; [HIGHDS]= 传输到的最低地址减去200八进制。
;
BLTU:	JSR	REASON		;确保字符串空间不会被越界。
				;
	STWD	STREND
BLTUC:	SEC			;准备减法。
	LDA	HIGHTR
	SBC	LOWTR		;计算要移动的事物数量。
	STA	INDEX		;稍后保存。
	TAY
	LDA	HIGHTR+1
	SBC	LOWTR+1
	TAX			;将其放入计数器寄存器。
	INX			;以便计数器算法工作。
	TYA			;查看计数的低位是否为零。
	BEQ	DECBLT		;是，开始移动块。
	LDA	HIGHTR		;否，必须修改基地址。
	SEC
	SBC	INDEX		;由于[HIGHTR].GT.[LOWTR]，借位关闭。
	STA	HIGHTR		;保存修改后的基地址。
	BCS	BLT1		;如果无借位，则推送它。
	DEC	HIGHTR+1	;借位意味着从高位字节减1。
	SEC
BLT1:	LDA	HIGHDS		;修改目标地址的基地址。
	SBC	INDEX
	STA	HIGHDS
	BCS	MOREN1		;无借位。
	DEC	HIGHDS+1	;递减高位字节。
	BCC	MOREN1		;总是跳过。
BLTLP:	LDADY	HIGHTR		;获取要移动的字节
	STADY	HIGHDS		;移入移出。
MOREN1: DEY
	BNE	BLTLP
	LDADY	HIGHTR		;移动块的最后一个字节。
	STADY	HIGHDS
DECBLT: DEC	HIGHTR+1
	DEC	HIGHDS+1	;开始新块。
	DEX
	BNE	MOREN1
	RTS			;返回调用者。

;
; 此例程用于确保堆栈保留给定数量的位置。
;    调用为：
;	LDAI	需要的2字节条目数。
;	JSR	GETSTK
;
;
; 此例程必须由任何在堆栈上放置任意数量内容的例程调用，
; 例如，任何递归例程如"FRMEVL"。
; 它也被诸如"GOSUB"和"FOR"之类的例程调用，这些例程在堆栈上创建永久条目。
;
;
;
; 仅使用并释放保证的NUMLEV位置的例程不需要调用此例程。
;
;
;
; 退出时：
;    [A] 和 [X] 已被修改。
;
GETSTK: ASL	A,		;将[A]乘以2。注意，清除C位。
	ADCI	2*NUMLEV+<3*ADDPRC>+13	;确保2*NUMLEV+13个位置
				;（13因为FBUFFR）
	BCS	OMERR		;将保留在堆栈中。
	STA	INDEX
	TSX			;获取堆栈指针。
	CPX	INDEX		;比较。
	BCC	OMERR		;如果堆栈.LE.INDEX1，则OM。
	RTS

;
; [Y,A] IS A CERTAIN ADDRESS. "REASON" MAKES SURE ;[Y,A] 是一个特定地址。
; IT IS LESS THAN [FRETOP]. ; "REASON" 确保它小于 [FRETOP]。
;
REASON: CPY	FRETOP+1
	BCC	REARTS
	BNE	TRYMOR		;GO GARB COLLECT. ; 去进行垃圾回收
	CMP	FRETOP
	BCC	REARTS
TRYMOR: PHA
	LDXI	8+ADDPRC	;IF TEMPF2 HAS ZERO IN BETWEEN. ; 如果 TEMPF2 中间有零
	TYA
REASAV: PHA
	LDA	HIGHDS-1,X	;SAVE HIGHDS ON STACK. ; 将 HIGHDS 保存到堆栈
	DEX
	BPL	REASAV		;PUT 8 OF THEM ON STK. ; 将 8 个它们放入堆栈
	JSR	GARBA2		;GO GARB COLLECT. ; 去进行垃圾回收
	LDXI	256-8-ADDPRC
REASTO: PLA
	STA	HIGHDS+8+ADDPRC,X	;RESTORE AFTER GARB COLLECT. ; 垃圾回收后恢复
	INX
	BMI	REASTO
	PLA
	TAY
	PLA			;RESTORE A AND Y. ; 恢复 A 和 Y
	CPY	FRETOP+1	;COMPARE HIGHS ; 比较高位
	BCC	REARTS
	BNE	OMERR		;HIGHER IS BAD. ; 更高是不好的
	CMP	FRETOP		;AND THE LOWS. ; 以及低位
	BCS	OMERR
REARTS: RTS

PAGE
SUBTTL	ERROR HANDLER, READY, TERMINAL INPUT, COMPACTIFY, NEW, REINIT. ; 错误处理程序、READY、终端输入、压缩、NEW、重新初始化
OMERR:	LDXI	ERROM
ERROR:
IFN	REALIO,<
	LSR	CNTWFL>		;FORCE OUTPUT. ; 强制输出
IFN	EXTIO,<
	LDA	CHANNL		;CLOSE NON-TERMINAL CHANNEL. ; 关闭非终端通道
	BEQ	ERRCRD
	JSR	CQCCHN		;CLOSE IT. ; 关闭它
	LDAI	0
	STA	CHANNL>
ERRCRD: JSR	CRDO		;OUTPUT CRLF. ; 输出回车换行
	JSR	OUTQST		;PRINT A QUESTION MARK ; 打印一个问号
IFE LNGERR,<
	LDA	ERRTAB,X,	;GET FIRST CHR OF ERR MSG. ; 获取错误消息的第一个字符
	JSR	OUTDO		;OUTPUT IT. ; 输出它
	LDA	ERRTAB+1,X,	;GET SECOND CHR. ; 获取第二个字符
	JSR	OUTDO>		;OUTPUT IT. ; 输出它
IFN LNGERR,<
GETERR: LDA	ERRTAB,X
	PHA
	ANDI	127		;GET RID OF HIGH BIT. ; 去掉高位
	JSR	OUTDO		;OUTPUT IT. ; 输出它
	INX
	PLA			;LAST CHAR OF MESSAGE? ; 消息的最后一个字符？
	BPL	GETERR>		;NO. GO GET NEXT AND OUTPUT IT. ; 否，去获取下一个并输出
TYPERR: JSR	STKINI		;RESET THE STACK AND FLAGS. ; 重置堆栈和标志
	LDWDI	ERR		;GET PNTR TO " ERROR". ; 获取指向“ ERROR”的指针
ERRFIN: JSR	STROUT		;OUTPUT IT. ; 输出它
	LDY	CURLIN+1
	INY			;WAS NUMBER 64000? ; 号码是 64000 吗？
	BEQ	READY		;YES, DON'T TYPE LINE NUMBER. ; 是的，不键入行号
	JSR	INPRT
READY:
IFN	REALIO,<
	LSR	CNTWFL>		;TURN OUTPUT BACK ON IF SUPRESSED ; 如果被抑制，重新打开输出
	LDWDI	REDDY		;SAY "OK". ; 说“OK”
IFN	REALIO-3,<
	JSR	RDYJSR>		;OR GO TO INIT IF INIT ERROR. ; 或者如果初始化错误则转到 INIT
IFE	REALIO-3,<
	JSR	STROUT>		;NO INIT ERRORS POSSIBLE. ; 不可能有初始化错误
MAIN:	JSR	INLIN		;GET A LINE FROM TERMINAL. ; 从终端获取一行
	STXY	TXTPTR
	JSR	CHRGET
	TAX			;SET ZERO FLAG BASED ON [A] ; 基于 [A] 设置零标志
				;THIS DISTINGUISHES ":" AND 0 ; 这区分了“:”和 0
	BEQ	MAIN		;IF BLANK LINE, GET ANOTHER. ; 如果是空行，获取另一行
	LDXI	255		;SET DIRECT LINE NUMBER. ; 设置直接行号
	STX	CURLIN+1
	BCC	MAIN1		;IS A LINE NUMBER. NOT DIRECT. ; 是一个行号。不是直接的
	JSR	CRUNCH		;COMPACTIFY. ; 压缩
	JMP	GONE		;EXECUTE IT. ; 执行它
MAIN1:	JSR	LINGET		;READ LINE NUMBER INTO "LINNUM". ; 将行号读入“LINNUM”
	JSR	CRUNCH
	STY	COUNT		;RETAIN CHARACTER COUNT. ; 保留字符计数
	JSR	FNDLIN
	BCC	NODEL		;NO MATCH, SO DON'T DELETE. ; 不匹配，所以不删除
	LDYI	1
	LDADY	LOWTR
	STA	INDEX1+1
	LDA	VARTAB
	STA	INDEX1
	LDA	LOWTR+1		;SET TRANSFER TO. ; 设置传输到
	STA	INDEX2+1
	LDA	LOWTR
	DEY
	SBCDY	LOWTR		;COMPUTE NEGATIVE LENGTH. ; 计算负长度
	CLC
	ADC	VARTAB		;COMPUTE NEW VARTAB. ; 计算新的 VARTAB
	STA	VARTAB
	STA	INDEX2		;SET LOW OF TRANS TO. ; 设置传输的低位
	LDA	VARTAB+1
	ADCI	255
	STA	VARTAB+1	;COMPUTE HIGH OF VARTAB. ; 计算 VARTAB 的高位
	SBC	LOWTR+1		;COMPUTE NUMBER OF BLOCKS TO MOVE. ; 计算要移动的块数
	TAX
	SEC
	LDA	LOWTR
	SBC	VARTAB		;COMPUTE OFFSET. ; 计算偏移量
	TAY
	BCS	QDECT1		;IF VARTAB.LE.LOWTR, ; 如果 VARTAB.LE.LOWTR
	INX			;DECR DUE TO CARRY, AND ; 由于进位而递减，并且
	DEC	INDEX2+1	;DECREMENT STORE SO CARRY WORKS. ; 递减存储以使进位工作
QDECT1: CLC
	ADC	INDEX1
	BCC	MLOOP
	DEC	INDEX1+1
	CLC			;FOR LATER ADCQ ; 为后面的 ADCQ
MLOOP:	LDADY	INDEX1
	STADY	INDEX2
	INY
	BNE	MLOOP		;BLOCK DONE? ; 块完成了吗？
	INC	INDEX1+1
	INC	INDEX2+1
	DEX
	BNE	MLOOP		;DO ANOTHER BLOCK. ALWAYS. ; 总是做另一个块
NODEL:	JSR	RUNC		;RESET ALL VARIABLE INFO SO GARBAGE ; 重置所有变量信息，以便垃圾
				;COLLECTION CAUSED BY REASON WILL WORK ; 由 REASON 引起的回收将工作
	JSR	LNKPRG		;FIX UP THE LINKS ; 修复链接
	LDA	BUF		;SEE IF ANYTHNG THERE ; 看看那里有什么
	BEQ	MAIN
	CLC
	LDA	VARTAB
	STA	HIGHTR		;SETUP HIGHTR. ; 设置 HIGHTR
	ADC	COUNT		;ADD LENGTH OF LINE TO INSERT. ; 添加要插入的行的长度
	STA	HIGHDS		;THIS GIVES DEST ADDR. ; 这给出了目标地址
	LDY	VARTAB+1
	STY	HIGHTR+1	;SAME FOR HIGH ORDERS. ; 高位也一样
	BCC	NODELC
	INY
NODELC: STY	HIGHDS+1
	JSR	BLTU
IFN	BUFPAG,<
	LDWD	LINNUM		;POSITION THE BINARY LINE NUMBER ; 定位二进制行号
	STWD	BUF-2>		;IN FRONT OF BUF ; 在 BUF 前面
	LDWD	STREND
	STWD	VARTAB
	LDY	COUNT
	DEY
STOLOP: LDA	BUF-4,Y
	STADY	LOWTR
	DEY
	BPL	STOLOP
FINI:	JSR	RUNC		;DO CLEAR & SET UP STACK. ; 执行 CLEAR 并设置堆栈
				;AND SET [TXTPTR] TO [TXTTAB]-1. ; 并将 [TXTPTR] 设置为 [TXTTAB]-1
	JSR	LNKPRG		;FIX UP PROGRAM LINKS ; 修复程序链接
	JMP	MAIN
LNKPRG: LDWD	TXTTAB		;SET [INDEX] TO [TXTTAB]. ; 将 [INDEX] 设置为 [TXTTAB]
	STWD	INDEX
	CLC
;
; CHEAD GOES THROUGH PROGRAM STORAGE AND FIXES ; CHEAD 遍历程序存储并修复所有链接。每行的末尾通过搜索末尾的零来找到。
; UP ALL THE LINKS. THE END OF EACH LINE IS FOUND ; 双零链接用于检测程序的结束。
; BY SEARCHING FOR THE ZERO AT THE END.
; THE DOUBLE ZERO LINK IS USED TO DETECT THE END OF THE PROGRAM.
;
CHEAD:	LDYI	1
	LDADY	INDEX		;ARRIVED AT DOUBLE ZEROES? ; 到达双零了吗？
	BEQ	LNKRTS
	LDYI	4
CZLOOP: INY			;THERE IS AT LEAST ONE BYTE. ; 至少有一个字节
	LDADY	INDEX
	BNE	CZLOOP		;NO, CONTINUE SEARCHING. ; 不，继续搜索
	INY			;GO ONE BEYOND. ; 再前进一个
	TYA
	ADC	INDEX
	TAX
	LDYI	0
	STADY	INDEX
	LDA	INDEX+1
	ADCI	0
	INY
	STADY	INDEX
	STX	INDEX
	STA	INDEX+1
	BCCA	CHEAD		;ALWAYS BRANCHES. ; 总是分支
LNKRTS: RTS
;
; THIS IS THE LINE INPUT ROUTINE. ; 这是行输入例程。
; IT READS CHARACTERS INTO BUF USING BACKARROW (UNDERSCORE, OR ; 它使用 BACKARROW（下划线或 SHIFT O）作为删除字符，@ 作为行删除字符，将字符读入 BUF。
; SHIFT O) AS THE DELETE CHARACTER AND @ AS THE ; 如果键入了超过 BUFLEN 个字符，则在键入 BACKARROW 或 @ 或 CR 之前不会进行回显。
; LINE DELETE CHARACTER. IF MORE THAN BUFLEN CHARACTERS ; 每个额外字符都会键入 Control-G。
; ARE TYPED, NO ECHOING IS DONE UNTIL A BACKARROW OR @ OR CR ; 该例程在 INLIN 处进入。
; IS TYPED. CONTROL-G WILL BE TYPED FOR EACH EXTRA CHARACTER.
; THE ROUTINE IS ENTERED AT INLIN.
;
IFE	REALIO-4,<
INLIN:	LDXI	128		;NO PROMPT CHARACTER ; 无提示字符
	STX	CQPRMP
	JSR	CQINLN		;GET A LINE ONTO PAGE 2 ; 获取一行到第2页
	CPXI	BUFLEN-1
	BCS	GDBUFS		;NOT TOO MANY CHARACTERS ; 字符不太多
	LDXI	BUFLEN-1
GDBUFS: LDAI	0		;PUT A ZERO AT THE END ; 在末尾放一个零
	STA	BUF,X
	TXA
	BEQ	NOCHR
LOPBHT: LDA	BUF-1,X
	ANDI	127
	STA	BUF-1,X
	DEX
	BNE	LOPBHT
NOCHR:	LDAI	0
	LDXYI	<BUF-1>		;POINT AT THE BEGINNING ; 指向开头
	RTS>
IFN	REALIO-4,<
IFN	REALIO-3,<
LINLIN: IFE	REALIO-2,<
	JSR	OUTDO>		;ECHO IT. ; 回显它
	DEX			;BACKARROW SO BACKUP PNTR AND ; BACKARROW 所以备份指针并且
	BPL	INLINC		;GET ANOTHER IF COUNT IS POSITIVE. ; 如果计数为正，则获取另一个
INLINN: IFE	REALIO-2,<
	JSR	OUTDO>		;PRINT THE @ OR A SECOND BACKARROW ; 打印 @ 或第二个 BACKARROW
				;IF THERE WERE TOO MANY. ; 如果有太多
	JSR	CRDO>
INLIN:	LDXI	0
INLINC: JSR	INCHR		;GET A CHARACTER. ; 获取一个字符
IFN REALIO-3,<
	CMPI	7		;IS IT BOB ALBRECHT RINGING THE BELL ; 是 Bob Albrecht 在敲钟吗
				;FOR SCHOOL KIDS? ; 为了学童？
	BEQ	GOODCH>
	CMPI	13		;CARRIAGE RETURN? ; 回车？
	BEQ	FININ1		;YES, FINISH UP. ; 是的，完成
IFN	REALIO-3,<
	CMPI	32		;CHECK FOR FUNNY CHARACTERS. ; 检查有趣字符
	BCC	INLINC
	CMPI	125		;IS IT TILDA OR DELETE? ; 是波浪号还是删除？
	BCS	INLINC		;BIG BAD ONES TOO. ; 大的坏的也是
	CMPI	"@"		;LINE DELETE? ; 行删除？
	BEQ	INLINN		;YES. ; 是的
	CMPI	"_"		;CHARACTER DELETE? ; 字符删除？
	BEQ	LINLIN>		;YES. ; 是的
GOODCH:
IFN	REALIO-3,<
	CPXI	BUFLEN-1	;LEAVE ROOM FOR NULL. ; 为 NULL 留出空间
			;COMMO ASSURES US NEVER MORE THAN BUFLEN. ; COMMO 确保我们从不超出 BUFLEN
	BCS	OUTBEL>
	STA	BUF,X
	INX
IFE	REALIO-2,<SKIP2>
IFN	REALIO-2,<BNE INLINC>
IFN REALIO-3,<
OUTBEL: LDAI	7
IFN	REALIO,<
	JSR	OUTDO>		;ECHO IT. ; 回显它
	BNE	INLINC>		;CYCLE ALWAYS. ; 总是循环
FININ1: JMP	FININL>		;GO TO FININL FAR, FAR AWAY. ; 转到遥远的 FININL
INCHR:	
IFE	REALIO-3,<
	JSR	CQINCH>		;FOR COMMODORE. ; 用于 Commodore
IFE	REALIO-2,<
INCHRL: LDA	^O176000
	REPEAT	4,<NOP>
	LSR	A,
	BCC	INCHRL
	LDA	^O176001	;GET THE CHARACTER. ; 获取字符
	REPEAT	4,<NOP>
	ANDI	127>
IFE	REALIO-1,<
	JSR	^O17132>	;1E5A FOR MOS TECH. ; MOS Tech 为 1E5A
IFE	REALIO-4,<
	JSR	CQINCH		;FD0C FOR APPLE COMPUTER. ; Apple Computer 为 FD0C
	ANDI	127>
IFE	REALIO,<
	TJSR	INSIM##>	;GET A CHARACTER FROM SIMULATOR ; 从模拟器获取一个字符

IFN	REALIO,<
IFN	EXTIO,<
	LDY	CHANNL		;CNT-O HAS NO EFFECT IF NOT FROM TERM. ; 如果不是来自终端，CNT-O 无效
	BNE	INCRTS>
	CMPI	CONTW		;SUPPRESS OUTPUT CHARACTER (^W). ; 抑制输出字符 (^W)
	BNE	INCRTS		;NO, RETURN. ; 不，返回
	PHA
	COM	CNTWFL		;COMPLEMENT ITS STATE. ; 补充其状态
	PLA>
INCRTS: RTS			;END OF INCHR. ; INCHR 结束
	
;
; ALL "RESERVED" WORDS ARE TRANSLATED INTO SINGLE ; 所有“保留”字都被转换为最高位设置的单个字节。
; BYTES WITH THE MSB ON. THIS SAVES SPACE AND TIME ; 这通过在执行期间允许表分派来节省空间和时间。
; BY ALLOWING FOR TABLE DISPATCH DURING EXECUTION. ; 因此，所有语句以它们在 STMDSP 中出现的相同顺序一起出现在保留字列表中。
; THEREFORE ALL STATEMENTS APPEAR TOGETHER IN THE
; RESERVED WORD LIST IN THE SAME ORDER THEY
; APPEAR IN STMDSP.
;
BUFOFS=0			;THE AMOUNT TO OFFSET THE LOW BYTE ; 偏移低字节的量
				;OF THE TEXT POINTER TO GET TO BUF ; 文本指针到 BUF
				;AFTER TXTPTR HAS BEEN SETUP TO POINT INTO BUF ; 在 TXTPTR 设置为指向 BUF 之后
IFN	BUFPAG,<
BUFOFS=<BUF/256>*256>
CRUNCH: LDX	TXTPTR		;SET SOURCE POINTER. ; 设置源指针
	LDYI	4		;SET DESTINATION OFFSET. ; 设置目标偏移
	STY	DORES		;ALLOW CRUNCHING. ; 允许压缩
KLOOP:	LDA	BUFOFS,X
IFE	REALIO-3,<
	BPL	CMPSPC		;GO LOOK AT SPACES. ; 去看看空格
	CMPI	PI		;PI?? ; PI？？
	BEQ	STUFFH		;GO SAVE IT. ; 去保存它
	INX			;SKIP NO PRINTING. ; 跳过不打印
	BNE	KLOOP>		;ALWAYS GOES. ; 总是去
CMPSPC: CMPI	" "		;IS IT A SPACE TO SAVE? ; 是要保存的空格吗？
	BEQ	STUFFH		;YES, GO SAVE IT. ; 是的，去保存它
	STA	ENDCHR		;IF IT'S A QUOTE, THIS WILL ; 如果是引号，这将
				;STOP LOOP WHEN OTHER QUOTE APPEARS. ; 在另一个引号出现时停止循环
	CMPI	34		;QUOTE SIGN? ; 引号？
	BEQ	STRNG		;YES, DO SPECIAL STRING HANDLING. ; 是的，进行特殊字符串处理
	BIT	DORES		;TEST FLAG. ; 测试标志
	BVS	STUFFH		;NO CRUNCH, JUST STORE. ; 不压缩，仅存储
	CMPI	"?"		;A QMARK? ; 问号？
	BNE	KLOOP1
	LDAI	PRINTK		;YES, STUFF A "PRINT" TOKEN. ; 是的，填充一个“PRINT”令牌
	BNE	STUFFH		;ALWAYS GO TO STUFFH. ; 总是去 STUFFH
KLOOP1: CMPI	"0"		;SKIP NUMERICS. ; 跳过数字
	BCC	MUSTCR
	CMPI	60		;":" AND ";" ARE ENTERED STRAIGHTAWAY. ; “:”和“;”直接进入
	BCC	STUFFH
MUSTCR: STY	BUFPTR		;SAVE BUFFER POINTER. ; 保存缓冲区指针
	LDYI	0		;LOAD RESLST POINTER. ; 加载 RESLST 指针
	STY	COUNT		;ALSO CLEAR COUNT. ; 同时清除计数
	DEY
	STX	TXTPTR		;SAVE TEXT POINTER FOR LATER USE. ; 保存文本指针供以后使用
	DEX
RESER:	INY
RESPUL: INX
RESCON: LDA	BUFOFS,X
	SEC			;PREPARE TO SUBSTARCT. ; 准备减法
	SBC	RESLST,Y	;CHARACTERS EQUAL? ; 字符相等？
	BEQ	RESER		;YES, CONTINUE SEARCH. ; 是的，继续搜索
	CMPI	128		;NO BUT MAYBE THE END IS HERE. ; 不，但可能结束在这里
	BNE	NTHIS		;NO, TRULY UNEQUAL. ; 不，真正不相等
	ORA	COUNT
GETBPT: LDY	BUFPTR		;GET BUFFER PNTR. ; 获取缓冲区指针
STUFFH: INX
	INY
	STA	BUF-5,Y
	LDA	BUF-5,Y
	BEQ	CRDONE		;NULL IMPLIES END OF LINE. ; NULL 表示行结束
	SEC			;PREPARE TO SUBSTARCT. ; 准备减法
	SBCI	":"		;IS IT A ":"? ; 是“:”吗？
	BEQ	COLIS		;YES, ALLOW CRUNCHING AGAIN. ; 是的，再次允许压缩
	CMPI	DATATK-":"	;IS IT A DATATK? ; 是 DATATK 吗？
	BNE	NODATT		;NO, SEE IF IT IS REM TOKEN. ; 不，看看是否是 REM 令牌
COLIS:	STA	DORES		;SETUP FLAG. ; 设置标志
NODATT: SEC			;PREP TO SBCQ ; 准备 SBCQ
	SBCI	REMTK-":"	;REM ONLY STOPS ON NULL. ; REM 仅在 NULL 时停止
	BNE	KLOOP		;NO, CONTINUE CRUNCHING. ; 不，继续压缩
	STA	ENDCHR		;REM STOPS ONLY ON NULL, NOT : OR ". ; REM 仅在 NULL 时停止，而不是 : 或 "
STR1:	LDA	BUFOFS,X
	BEQ	STUFFH		;YES, END OF LINE, SO DONE. ; 是的，行结束，所以完成
	CMP	ENDCHR		;END OF GOBBLE? ; 吞噬结束？
	BEQ	STUFFH		;YES, DONE WITH STRING. ; 是的，字符串处理完成
STRNG:	INY			;INCREMENT BUFFER POINTER. ; 增加缓冲区指针
	STA	BUF-5,Y
	INX
	BNE	STR1		;PROCESS NEXT CHARACTER. ; 处理下一个字符
NTHIS:	LDX	TXTPTR		;RESTORE TEXT POINTER. ; 恢复文本指针
	INC	COUNT		;INCREMENT RES WORD COUNT. ; 增加保留字计数
NTHIS1: INY
	LDA	RESLST-1,Y,	;GET RES CHARACTER. ; 获取保留字符
	BPL	NTHIS1		;END OF ENTRY? ; 条目结束？
	LDA	RESLST,Y,	;YES. IS IT THE END? ; 是的。是结束吗？
	BNE	RESCON		;NO, TRY THE NEXT WORD. ; 不，尝试下一个单词
	LDA	BUFOFS,X	;YES, END OF TABLE. GET 1ST CHR. ; 是的，表结束。获取第一个字符
	BPL	GETBPT		;STORE IT AWAY (ALWAYS BRANCHES). ; 存储它（总是分支）
CRDONE: STA	BUF-3,Y,	;SO THAT IF THIS IS A DIR STATEMENT ; 因此，如果这是一个直接语句
				;ITS END WILL LOOK LIKE END OF PROGRAM. ; 它的结束将看起来像程序结束
IFN	<<BUF+BUFLEN>/256>-<<BUF-1>/256>,<
	DEC	TXTPTR+1>
	LDAI	<BUF&255>-1	;MAKE TXTPTR POINT TO ; 使 TXTPTR 指向
	STA	TXTPTR		;CRUNCHED LINE. ; 压缩后的行
LISTRT: RTS			;RETURN TO CALLER. ; 返回调用者
;
; FNDLIN SEARCHES THE PROGRAM TEXT FOR THE LINE ; FNDLIN 在程序文本中搜索行号在“LINNUM”中传递的行。
; WHOSE NUMBER IS PASSED IN "LINNUM".
; THERE ARE TWO POSSIBLE RETURNS: ; 有两种可能的返回：
;
;	1) CARRY SET. ; 进位设置。
;	   LOWTR POINTS TO THE LINK FIELD IN THE LINE ; LOWTR 指向行中的链接字段，这是要搜索的行。
;	   WHICH IS THE ONE SEARCHED FOR.
;
;	2) CARRY NOT SET. ; 进位未设置。
;	   LINE NOT FOUND. [LOWTR] POINTS TO THE LINE IN THE ; 未找到行。[LOWTR] 指向程序中大于所寻行的行。
;	   PROGRAM GREATER THAN THE ONE SOUGHT AFTER.
;
FNDLIN: LDWX	TXTTAB		;LOAD [X,A] WITH [TXTTAB] ; 用 [TXTTAB] 加载 [X,A]
FNDLNC: LDYI	1
	STWX	LOWTR		;STORE [X,A] INTO LOWTR ; 将 [X,A] 存储到 LOWTR
	LDADY	LOWTR		;SEE IF LINK IS 0 ; 查看链接是否为 0
	BEQ	FLINRT
	INY
	INY
	LDA	LINNUM+1	;COMP HIGH ORDERS OF LINE NUMBERS. ; 比较行号的高位
	CMPDY	LOWTR
	BCC	FLNRTS		;NO SUCH LINE NUMBER. ; 没有这样的行号
	BEQ	FNDLO1
	DEY
	BNE	AFFRTS		;ALWAYS BRANCH. ; 总是分支
FNDLO1: LDA	LINNUM
	DEY
	CMPDY	LOWTR		;COMPARE LOW ORDERS. ; 比较低位
	BCC	FLNRTS		;NO SUCH NUMBER. ; 没有这样的号码
	BEQ	FLNRTS		;GO TIT. ; 去处理
AFFRTS: DEY
	LDADY	LOWTR		;FETCH LINK. ; 获取链接
	TAX
	DEY
	LDADY	LOWTR
	BCS	FNDLNC		;ALWAYS BRANCHES. ; 总是分支
FLINRT: CLC			;C MAY BE HIGH. ; C 可能为高
FLNRTS: RTS			;RETURN TO CALLER. ; 返回调用者
;
; THE "NEW" COMMAND CLEARS THE PROGRAM TEXT AS WELL
; AS VARIABLE SPACE. ; “NEW”命令清除程序文本以及变量空间。
;
SCRATH: BNE	FLNRTS		;MAKE SURE THERE IS A TERMINATOR. ; 确保有终止符
SCRTCH: LDAI	0		;GET A CLEARER. ; 获取清除器
	TAY			;SET UP INDEX. ; 设置索引
	STADY	TXTTAB		;CLEAR	FIRST LINK. ; 清除第一个链接
	INY
	STADY	TXTTAB
	LDA	TXTTAB
	CLC
	ADCI	2
	STA	VARTAB		;SETUP [VARTAB]. ; 设置 [VARTAB]
	LDA	TXTTAB+1
	ADCI	0
	STA	VARTAB+1
RUNC:	JSR	STXTPT
	LDAI	0		;SET ZERO FLAG ; 设置零标志
;
; THIS CODE IS FOR THE CLEAR COMMAND. ; 此代码用于 CLEAR 命令。
;
CLEAR:	BNE	STKRTS		;SYNTAX ERROR IF NO TERMINATOR. ; 如果没有终止符，则语法错误
;
; CLEAR INITIALIZES THE VARIABLE AND ; CLEAR 通过重置 ARYTAB（简单变量空间的末尾）和 STREND（数组存储的末尾）来初始化变量和数组空间。
; ARRAY SPACE BY RESETING ARYTAB (THE END OF SIMPLE VARIABLE SPACE) ; 它落入“STKINI”，后者重置堆栈。
; AND STREND (THE END OF ARRAY STORAGE). IT FALLS INTO "STKINI"
; WHICH RESETS THE STACK. 
;
CLEARC: LDWD	MEMSIZ		;FREE UP STRING SPACE. ; 释放字符串空间
	STWD	FRETOP
IFN	EXTIO,<
	JSR	CQCALL>		;CLOSE ALL OPEN FILES. ; 关闭所有打开的文件
	LDWD	VARTAB		;LIBERATE THE ; 释放
	STWD	ARYTAB		;VARIABLES AND ; 变量和
	STWD	STREND		;ARRAYS. ; 数组
FLOAD:	JSR	RESTOR		;RESTORE DATA. ; 恢复数据
;
; STKINI RESETS THE STACK POINTER ELIMINATING ; STKINI 重置堆栈指针，消除 GOSUB 和 FOR 上下文。字符串临时变量被释放，SUBFLG 被重置。禁止继续。
; GOSUB AND FOR CONTEXT. STRING TEMPORARIES ARE FREED ; 并且在堆栈底部留下一个虚拟条目，以便“FNDFOR”总是在堆栈底部找到一个非“FOR”条目。
; UP, SUBFLG IS RESET. CONTINUING IS PROHIBITED.
; AND A DUMMY ENTRY IS LEFT AT THE BOTTOM OF THE STACK SO "FNDFOR" WILL ALWAYS
; FIND A NON-"FOR" ENTRY AT THE BOTTOM OF THE STACK.
;
STKINI: LDXI	TEMPST		;INITIALIZE STRING TEMPORARIES. ; 初始化字符串临时变量
	STX	TEMPPT
	PLA			;SETUP RETURN ADDRESS. ; 设置返回地址
	TAY
	PLA
	LDXI	STKEND-257
	TXS
	PHA
	TYA
	PHA
	LDAI	0
	STA	OLDTXT+1	;DISALLOWING CONTINUING ; 禁止继续
	STA	SUBFLG		;ALLOW SUBSCRIPTS. ; 允许下标
STKRTS: RTS

STXTPT: CLC
	LDA	TXTTAB
	ADCI	255
	STA	TXTPTR
	LDA	TXTTAB+1
	ADCI	255
	STA	TXTPTR+1	;SETUP TEXT POINTER. ; 设置文本指针
	RTS
PAGE
SUBTTL	THE "LIST" COMMAND. ; “LIST”命令

LIST:	BCC	GOLST		;IT IS A DIGIT. ; 它是一个数字
	BEQ	GOLST		;IT IS A TERMINATOR. ; 它是一个终止符
	CMPI	MINUTK		;DASH PRECEDING? ; 前面有破折号？
	BNE	STKRTS		;NO, SO SYNTAX ERROR. ; 不，所以语法错误
GOLST:	JSR	LINGET		;GET LINE NUMBER INTO NUMLIN. ; 将行号获取到 NUMLIN
	JSR	FNDLIN		;FIND LINE .GE. [NUMLIN]. ; 查找行 .GE. [NUMLIN]
	JSR	CHRGOT		;GET LAST CHARACTER. ; 获取最后一个字符
	BEQ	LSTEND		;IF END OF LINE, # IS THE END. ; 如果行结束，# 就是结束
	CMPI	MINUTK		;DASH? ; 破折号？
	BNE	FLNRTS		;IF NOT, SYNTAX ERROR. ; 如果不是，语法错误
	JSR	CHRGET		;GET NEXT CHAR. ; 获取下一个字符
	JSR	LINGET		;GET END #. ; 获取结束 #
	BNE	FLNRTS		;IF NOT TERMINATOR, ERROR. ; 如果不是终止符，错误
LSTEND: PLA
	PLA			;GET RID OF "NEWSTT" RTS ADDR. ; 去掉“NEWSTT”RTS 地址
	LDA	LINNUM		;SEE IF IT WAS EXISTENT. ; 查看它是否存在
	ORA	LINNUM+1
	BNE	LIST4		;IT WAS TYPED. ; 它被键入了
	LDAI	255
	STA	LINNUM
	STA	LINNUM+1	;MAKE IT HUGE. ; 使它巨大
LIST4:	LDYI	1
IFE	REALIO-3,<
	STY	DORES>
	LDADY	LOWTR		;IS LINK ZERO? ; 链接为零吗？
	BEQ	GRODY		;YES, GO TO READY. ; 是的，转到 READY
IFN	REALIO,<
	JSR	ISCNTC>		;LISTEN FOR CONT-C. ; 监听 CONT-C
	JSR	CRDO		;PRINT CRLF TO START WITH. ; 首先打印 CRLF
	INY
	LDADY	LOWTR
	TAX
	INY
	LDADY	LOWTR		;GET LINE NUMBER. ; 获取行号
	CMP	LINNUM+1	;SEE IF BEYOND LAST. ; 查看是否超出最后一个
	BNE	TSTDUN		;GO DETERMINE RELATION. ; 去确定关系
	CPX	LINNUM		;WAS EQUAL SO TEST LOW ORDER. ; 相等，所以测试低位
	BEQ	TYPLIN		;EQUAL, SO LIST IT. ; 相等，所以列出它
TSTDUN: BCS	GRODY		;IF LINE IS GR THAN LAST, THEN DUNE. ; 如果行大于最后一个，则完成
TYPLIN: STY	LSTPNT
	JSR	LINPRT		;PRINT AS INT WITHOUT LEADING SPACE. ; 打印为整数，无前导空格
	LDAI	" "		;ALWAYS PRINT SPACE AFTER NUMBER. ; 总是在数字后打印空格
PRIT4:	LDY	LSTPNT		;GET POINTER TO LINE BACK. ; 获取指向行的指针
	ANDI	127
PLOOP:	JSR	OUTDO		;PRINT CHAR. ; 打印字符
IFE	REALIO-3,<
	CMPI	34
	BNE	PLOOP1
	COM	DORES>		;IF QUOTE, COMPLEMENT FLAG. ; 如果是引号，补充标志
PLOOP1: INY
	BEQ	GRODY		;IF WE HAVE PRINTED 256 CHARACTERS ; 如果我们打印了 256 个字符
				;THE PROGRAM MUST BE MISFORMATED IN ; 程序必须格式错误
				;MEMORY DUE TO A BAD LOAD OR BAD ; 由于加载错误或硬件错误
				;HARDWARE. LET THE GUY RECOVER ; 让用户恢复
	LDADY	LOWTR		;GET NEXT CHAR. IS IT ZERO? ; 获取下一个字符。是零吗？
	BNE	QPLOP		;YES. END OF LINE. ; 是的。行结束
	TAY
	LDADY	LOWTR
	TAX
	INY
	LDADY	LOWTR
	STX	LOWTR
	STA	LOWTR+1
	BNE	LIST4		;BRANCH IF SOMETHING TO LIST. ; 如果有内容要列出，则分支
GRODY:	JMP	READY
				;IS IT A TOKEN? ; 是令牌吗？
QPLOP:	BPL	PLOOP		;NO, HEAD FOR PRINTER. ; 不，前往打印机
IFE	REALIO-3,<
	CMPI	PI
	BEQ	PLOOP
	BIT	DORES		;INSIDE QUOTE MARKS? ; 在引号内？
	BMI	PLOOP>		;YES, JUST TYPE THE CHARACTER. ; 是的，只需键入字符
	SEC
	SBCI	127		;GET RID OF SIGN BIT AND ADD 1. ; 去掉符号位并加 1
	TAX			;MAKE IT A COUNTER. ; 使其成为计数器
	STY	LSTPNT		;SAVE POINTER TO LINE. ; 保存指向行的指针
	LDYI	255		;LOOK AT RES'D WORD LIST. ; 查看保留字列表
RESRCH: DEX			;IS THIS THE RES'D WORD? ; 这是保留字吗？
	BEQ	PRIT3		;YES, GO TOSS IT UP.. ; 是的，去处理它
RESCR1: INY
	LDA	RESLST,Y,	;END OF ENTRY? ; 条目结束？
	BPL	RESCR1		;NO, CONTINUE PASSING. ; 不，继续传递
	BMI	RESRCH
PRIT3:	INY
	LDA	RESLST,Y
	BMI	PRIT4		;END OF RESERVED WORD. ; 保留字结束
	JSR	OUTDO		;PRINT IT. ; 打印它
	BNE	PRIT3		;END OF ENTRY? NO, TYPE REST. ; 条目结束？不，键入其余部分
PAGE
SUBTTL THE "FOR" STATEMENT. ; “FOR”语句
;
; A "FOR" ENTRY ON THE STACK HAS THE FOLLOWING FORMAT: ; 堆栈中的"FOR"条目具有以下格式：
;
; LOW ADDRESS ; 低地址
;	TOKEN (FORTK) 1 BYTE ; 令牌（FORTK）1字节
;	A POINTER TO THE LOOP VARIABLE 2 BYTES ; 指向循环变量的指针 2字节
;	THE STEP 4+ADDPRC BYTES ; 步长 4+ADDPRC字节
;	A BYTE REFLECTING THE SIGN OF THE INCREMENT 1 BYTE ; 反映增量符号的字节 1字节
;	THE UPPER VALUE 4+ADDPRC BYTES ; 上限值 4+ADDPRC字节
;	THE LINE NUMBER OF THE "FOR" STATEMENT 2 BYTES ; "FOR"语句的行号 2字节
;	A TEXT POINTER INTO THE "FOR" STATEMENT 2 BYTES ; 指向"FOR"语句文本的指针 2字节
; HIGH ADDRESS ; 高地址
;
; TOTAL 16+2*ADDPRC BYTES. ; 总计 16+2*ADDPRC字节。
;

FOR:	LDAI	128		;DON'T RECOGNIZE ; 不识别
	STA	SUBFLG		;SUBSCRIPTED VARIABLES. ; 下标变量
	JSR	LET		;READ THE VARIABLE AND ASSIGN IT ; 读取变量并为其赋值
				;THE CORRECT INITIAL VALUE AND STORE ; 正确的初始值并存储
				;A POINTER TO THE VARIABLE IN VARPNT. ; 指向变量的指针到VARPNT
	JSR	FNDFOR		;PNTR IS IN VARPNT, AND FORPNT. ; 指针在VARPNT和FORPNT中
	BNE	NOTOL		;IF NO MATCH, DON'T ELIMINATE ANYTHING. ; 如果不匹配，则不消除任何内容
	TXA			;MAKE IT ARITHMETICAL. ; 使其成为算术值
	ADCI	FORSIZ-3	;ELIMINATE ALMOST ALL. ; 消除几乎所有
	TAX			;NOTE C=1, THEN PLA, PLA. ; 注意C=1，然后PLA, PLA
	TXS			;MANIFEST. ; 显式设置堆栈指针
NOTOL:	PLA			;GET RID OF NEWSTT RETURN ADDRESS ; 去掉NEWSTT返回地址
	PLA			;IN CASE THIS IS A TOTALLY NEW ENTRY. ; 以防这是一个全新的条目
	LDAI	8+ADDPRC
	JSR	GETSTK		;MAKE SURE 16 BYTES ARE AVAILABLE. ; 确保有16字节可用
	JSR	DATAN		;GET A COUNT IN [Y] OF THE NUMBER OF ; 获取[Y]中"FOR"语句剩余字符数的计数
				;CHACRACTERS LEFT IN THE "FOR" STATEMENT ; [TXTPTR]不受影响
				;[TXTPTR] IS UNAFFECTED.
	CLC			;PREP TO ADD. ; 准备加法
	TYA			;SAVE IT FOR PUSHING. ; 保存以备压栈
	ADC	TXTPTR
	PHA
	LDA	TXTPTR+1
	ADCI	0
	PHA
	PSHWD	CURLIN		;PUT LINE NUMBER ON STACK. ; 将行号放入堆栈
	SYNCHK	TOTK		;"TO" IS NECESSARY. ; "TO"是必需的
	JSR	CHKNUM		;VALUE MUST BE A NUMBER. ; 值必须是数字
	JSR	FRMNUM		;GET UPPER VALUE INTO FAC. ; 获取上限值到FAC
	LDA	FACSGN		;PACK FAC. ; 打包FAC
	ORAI	127
	AND	FACHO
	STA	FACHO		;SET PACKED SIGN BIT. ; 设置打包符号位
	LDWDI	LDFONE
	STWD	INDEX1
	JMP	FORPSH		;PUT FAC ONTO STACK, PACKED. ; 将FAC放入堆栈，打包
LDFONE: LDWDI	FONE		;PUT 1.0 INTO FAC. ; 将1.0放入FAC
	JSR	MOVFM
	JSR	CHRGOT
	CMPI	STEPTK		;A STEP IS GIVEN? ; 是否给出了STEP？
	BNE	ONEON		;NO. ASSUME 1.0. ; 否，假定为1.0
	JSR	CHRGET		;YES. ADVANCE POINTER. ; 是，前进指针
	JSR	FRMNUM		;READ THE STEP. ; 读取步长
ONEON:	JSR	SIGN		;GET SIGN IN ACCA. ; 获取符号到ACCA
	JSR	PUSHF		;PUSH FAC ONTO STACK (THRU A). ; 将FAC压入堆栈（通过A）
	PSHWD	FORPNT		;PUT PNTR TO VARIABLE ON STACK. ; 将指向变量的指针放入堆栈
NXTCON: LDAI	FORTK		;PUT A FORTK ONTO STACK. ; 将FORTK放入堆栈
	PHA
;	BNEA	NEWSTT		;SIMULATE BNE TO NEWSTT. JUST FALL IN. ; 模拟BNE到NEWSTT，直接落入
PAGE
SUBTTL	NEW STATEMENT FETCHER. ; 新语句获取器
;
; BACK HERE FOR NEW STATEMENT. CHARACTER POINTED TO BY TXTPTR ; 新语句回到此处。TXTPTR指向的字符
; IS ":" OR END-OF-LINE. THE ADDRESS OF THIS LOC IS LEFT ; 是":"或行结束符。此位置的地址在语句执行时
; ON THE STACK WHEN A STATEMENT IS EXECUTED SO THAT ; 留在堆栈中，以便
; IT CAN MERELY DO A RTS WHEN IT IS DONE. ; 完成后只需执行RTS
;
NEWSTT: IFN	REALIO,<
	JSR	ISCNTC>		;LISTEN FOR CONTROL-C. ; 监听Control-C
	LDWD	TXTPTR		;LOOK AT CURRENT CHARACTER. ; 查看当前字符
IFN	BUFPAG,<
	CPYI	BUFPAG>		;SEE IF IT WAS DIRECT BY CHECK FOR BUF'S PAGE NUMBER ; 通过检查BUF的页码查看是否是直接语句
	BEQ	DIRCON
	STWD	OLDTXT		;SAVE IN CASE OF RESTART BY INPUT. ; 保存以备INPUT重新启动
IFN	BUFPAG,<DIRCON:>
	LDYI	0
IFE	BUFPAG,<DIRCON:>
	LDADY	TXTPTR
	BNE	MORSTS		;NOT NULL -- CHECK WHAT IT IS ; 非空——检查是什么
	LDYI	2		;LOOK AT LINK. ; 查看链接
	LDADY	TXTPTR		;IS LINK 0? ; 链接为0吗？
	CLC		;CLEAR CARRY FOR ENDCON AND MATH THAT FOLLOWS ; 为ENDCON及后续数学运算清除进位
	JEQ	ENDCON		;YES - RAN OFF THE END. ; 是 - 已到末尾
	INY			;PUT LINE NUMBER IN CURLIN. ; 将行号放入CURLIN
	LDADY	TXTPTR
	STA	CURLIN
	INY
	LDADY	TXTPTR
	STA	CURLIN+1
	TYA
	ADC	TXTPTR
	STA	TXTPTR
	BCC	GONE
	INC	TXTPTR+1
GONE:	JSR	CHRGET		;GET THE STATEMENT TYPE. ; 获取语句类型
	JSR	GONE3
	JMP	NEWSTT
GONE3:	BEQ	ISCRTS		;IF TERMINATOR, TRY AGAIN. ; 如果是终止符，重试
				;NO NEED TO SET UP CARRY SINCE IT WILL ; 无需设置进位，因为
				;BE ON IF NON-NUMERIC AND NUMERICS ; 非数字时它会开启，而数字
				;WILL CAUSE A SYNTAX ERROR LIKE THEY SHOULD ; 将按预期导致语法错误
GONE2:	SBCI	ENDTK		;" ON ... GOTO AND GOSUB" COME HERE. ; "ON ... GOTO AND GOSUB" 来到这里
	BCC	GLET
	CMPI	SCRATK-ENDTK+1
	BCS	SNERRX		;SOME RES'D WORD BUT NOT ; 某些保留字但不是
				;A STATEMENT RES'D WORD. ; 语句保留字
	ASL	A,		;MULTIPLY BY TWO. ; 乘以二
	TAY			;MAKE AN INDEX. ; 制作索引
	LDA	STMDSP+1,Y
	PHA
	LDA	STMDSP,Y
	PHA			;PUT DISP ADDR ONTO STACK. ; 将分发地址放入堆栈
	JMP	CHRGET
GLET:	JMP	LET		;MUST BE A LET ; 必须是LET
MORSTS: CMPI	":"
	BEQ	GONE		;IF A ":" CONTINUE STATEMENT ; 如果是":"继续语句
SNERR1: JMP	SNERR		;NEITHER 0 OR ":" SO SYNTAX ERROR ; 既不是0也不是":"所以语法错误
SNERRX: CMPI	GOTK-ENDTK
	BNE	SNERR1
	JSR	CHRGET		;READ IN THE CHARACTER AFTER "GO " ; 读取"GO "后的字符
	SYNCHK	TOTK
	JMP	GOTO
PAGE
SUBTTL	RESTORE,STOP,END,CONTINUE,NULL,CLEAR. ; RESTORE,STOP,END,CONTINUE,NULL,CLEAR

RESTOR: SEC
	LDA	TXTTAB
	SBCI	1
	LDY	TXTTAB+1
	BCS	RESFIN
	DEY
RESFIN: STWD	DATPTR		;READ FINISHES COME TO "RESFIN". ; 读取完成来到"RESFIN"
ISCRTS: RTS

IFE	REALIO-1,<
ISCNTC: LDAI	1
	BIT	^O13500
	BMI	ISCRTS
	LDXI	8
	LDAI	3
	CMPI	3>
IFE	REALIO-2,<
ISCNTC: LDA	^O176000
	REPEAT	4,<NOP>
	LSR	A,
	BCC	ISCRTS
	JSR	INCHR		;EAT CHAR THAT WAS TYPED ; 吃掉已键入的字符
	CMPI	3>		;WAS IT A CONTROL-C?? ; 是Control-C吗？

IFE	REALIO-4,<
ISCNTC: LDA	^O140000	;CHECK THE CHARACTER ; 检查字符
	CMPI	^O203
	BEQ	ISCCAP
	RTS
ISCCAP: JSR	INCHR
	CMPI	^O203>
STOP:	BCS	STOPC		;MAKE [C] NONZERO AS A FLAG. ; 使[C]非零作为标志
END:	CLC
STOPC:	BNE	CONTRT		;RETURN IF NOT CONT-C OR ; 如果不是CONT-C或
				;IF NO TERMINATOR FOR STOP OR END. ; STOP或END没有终止符则返回
				;[C]=0 SO WILL NOT PRINT "BREAK". ; [C]=0所以不会打印"BREAK"
	LDWD	TXTPTR
IFN	BUFPAG,<
	LDX	CURLIN+1
	INX>
	BEQ	DIRIS
	STWD	OLDTXT
STPEND: LDWD	CURLIN
	STWD	OLDLIN
DIRIS:	PLA			;POP OFF NEWSTT ADDR. ; 弹出NEWSTT地址
	PLA
ENDCON: LDWDI	BRKTXT
IFN	REALIO,<
	LDXI	0
	STX	CNTWFL>
	BCC	GORDY		;CARRY CLEAR SO DON'T PRINT "BREAK". ; 进位清除所以不打印"BREAK"
	JMP	ERRFIN
GORDY:	JMP	READY		;TYPE "READY". ; 打印"READY"

IFE	REALIO,<
DDT:	PLA			;GET RID OF NEWSTT RETURN. ; 去掉NEWSTT返回
	PLA
	HRRZ	14,.JBDDT##
	JRST	0(14)>
CONT:	BNE	CONTRT		;MAKE SURE THERE IS A TERMINATOR. ; 确保有终止符
	LDXI	ERRCN		;CONTINUE ERROR. ; 继续错误
	LDY	OLDTXT+1	;A STORED TXTPTR OF ZERO IS SETUP ; 存储的TXTPTR为零由STKINI设置
				;BY STKINI AND INDICATES THERE IS ; 表示没有
				;NOTHING TO CONTINUE. ; 可继续的内容
	JEQ	ERROR		;"STOP", "END", TYPING CRLF TO ; "STOP", "END", 对"INPUT"键入CRLF
				;"INPUT" AND  ^C SETUP OLDTXT. ; 和^C设置OLDTXT
	LDA	OLDTXT
	STWD	TXTPTR
	LDWD	OLDLIN
	STWD	CURLIN
CONTRT: RTS			;RETURN TO CALLER. ; 返回调用者

IFN	NULCMD,<
NULL:	JSR	GETBYT
	BNE	CONTRT		;MAKE SURE THERE IS TERMINATOR. ; 确保有终止符
	INX
	CPXI	240		;IS THE NUMBER REASONABLE? ; 数字合理吗？
	BCS	FCERR1		;"FUNCTION CALL" ERROR. ; "函数调用"错误
	DEX			;BACK -1 ; 回退-1
	STX	NULCNT
	RTS
FCERR1: JMP	FCERR>
PAGE
SUBTTL	LOAD AND SAVE SUBROUTINES. ; 加载和保存子程序

IFE	REALIO-1,<		;KIM CASSETTE I/O ; KIM盒式磁带I/O
SAVE:	TSX			;SAVE STACK POINTER ; 保存堆栈指针
	STX	INPFLG
	LDAI	STKEND-256-200
	STA	^O362		;SETUP DUMMY STACK FOR KIM MONITOR ; 为KIM监视器设置虚拟堆栈
	LDAI	254		;MAKE ID BYTE EQUAL TO FF HEX ; 使ID字节等于FF十六进制
	STA	^O13771		;STORE INTO KIM ID ; 存储到KIM ID
	LDWD	TXTTAB		;START DUMPING FROM TXTTAB ; 从TXTTAB开始转储
	STWD	^O13765		;SETUP SAL,SAH ; 设置SAL,SAH
	LDWD	VARTAB		;STOP AT VARTAB ; 在VARTAB停止
	STWD	^O13767		;SETUP EAL,EAH ; 设置EAL,EAH
	JMP	^O14000
RETSAV: LDX	INPFLG		;RESORE THE REAL STACK POINTER ; 恢复真实堆栈指针
	TXS
	LDWDI	TAPMES		;SAY IT WAS DONE ; 说已完成
	JMP	STROUT
GLOAD:	DT"LOADED"
	0
TAPMES: DT"SAVED"
	ACRLF
	0
PATSAV: BLOCK 20
LOAD:	LDWD	TXTTAB		;START DUMPING IN AT TXTTAB ; 在TXTTAB开始转储
	STWD	^O13765		;SETUP SAL,SAH ; 设置SAL,SAH
	LDAI	255
	STA	^O13771
	LDWDI	RTLOAD
	STWD	^O1		;SET UP RETURN ADDRESS FOR LOAD ; 为加载设置返回地址
	JMP	^O14163		;GO READ THE DATA IN ; 去读取数据
RTLOAD: LDXI	STKEND-256		;RESET THE STACK ; 重置堆栈
	TXS
	LDWDI	READY
	STWD	^O1
	LDWDI	GLOAD		;TELL HIM IT WORKED ; 告诉他成功了
	JSR	STROUT
	LDXY	^O13755		;GET LAST LOCATION ; 获取最后位置
	TXA			;ITS ONE TOO BIG ; 它太大了
	BNE	DECVRT		;DECREMENT [X,Y] ; 递减[X,Y]
	NOP
DECVRT: NOP
	STXY	VARTAB		;SETUP NEW VARIABLE LOCATION ; 设置新的变量位置
	JMP	FINI>		;RELINK THE PROGRAM ; 重新链接程序
IFE	REALIO-4,<
SAVE:	SEC			;CALCLUATE PROGRAM SIZE IN POKER ; 计算POKER中的程序大小
	LDA	VARTAB
	SBC	TXTTAB
	STA	POKER
	LDA	VARTAB+1
	SBC	TXTTAB+1
	STA	POKER+1
	JSR	VARTIO
	JSR	CQCOUT		;WRITE PROGRAM SIZE [POKER] ; 写入程序大小[POKER]
	JSR	PROGIO
	JMP	CQCOUT		;WRITE PROGRAM. ; 写入程序

LOAD:	JSR	VARTIO
	JSR	CQCSIN		;READ SIZE OF PROGRAM INTO POKER ; 读取程序大小到POKER
	CLC
	LDA	TXTTAB		;CALCULATE VARTAB FROM SIZE AND ; 根据大小和TXTTAB计算VARTAB
	ADC	POKER
	STA	VARTAB
	LDA	TXTTAB+1
	ADC	POKER+1
	STA	VARTAB+1
	JSR	PROGIO
	JSR	CQCSIN		;READ PROGRAM. ; 读取程序
	LDWDI	TPDONE
	JSR	STROUT
	JMP	FINI

TPDONE: DT"LOADED"
	0

VARTIO: LDWDI	POKER
	STWD	^O74
	LDAI	POKER+2
	STWD	^O76
	RTS
PROGIO: LDWD	TXTTAB
	STWD	^O74
	LDWD	VARTAB
	STWD	^O76
	RTS>
PAGE
SUBTTL	RUN,GOTO,GOSUB,RETURN. ; RUN,GOTO,GOSUB,RETURN
RUN:	JEQ	RUNC		;IF NO LINE # ARGUMENT. ; 如果没有行号参数
	JSR	CLEARC		;CLEAN UP -- RESET THE STACK. ; 清理——重置堆栈
	JMP	RUNC2		;MUST REPLACE RTS ADDR. ; 必须替换RTS地址
;
; A GOSUB ENTRY ON THE STACK HAS THE FOLLOWING FORMAT: ; 堆栈中的GOSUB条目具有以下格式：
;
; LOW ADDRESS: ; 低地址：
;	THE GOSUTK ONE BYTE ; GOSUTK一个字节
;	THE LINE NUMBER OF THE GOSUB STATEMENT TWO BYTES ; GOSUB语句的行号两个字节
;	A POINTER INTO THE TEXT OF THE GOSUB TWO BYTES ; 指向GOSUB文本的指针两个字节
;
; HIGH ADDRESS. ; 高地址
;
; TOTAL FIVE BYTES. ; 总计五个字节
;
GOSUB:	LDAI	3
	JSR	GETSTK		;MAKE SURE THERE IS ROOM. ; 确保有空间
	PSHWD	TXTPTR		;PUSH ON THE TEXT POINTER. ; 压入文本指针
	PSHWD	CURLIN		;PUSH ON THE CURRENT LINE NUMBER. ; 压入当前行号
	LDAI	GOSUTK
	PHA			;PUSH ON A GOSUB TOKEN. ; 压入GOSUB令牌
RUNC2:	JSR	CHRGOT		;GET CHARACTER AND SET CODES FOR LINGET. ; 获取字符并为LINGET设置代码
	JSR	GOTO		;USE RTS SCHEME TO "NEWSTT". ; 使用RTS方案到"NEWSTT"
	JMP	NEWSTT

GOTO:	JSR	LINGET		;PICK UP THE LINE NUMBER IN "LINNUM". ; 获取"LINNUM"中的行号
	JSR	REMN		;SKIP TO END OF LINE. ; 跳到行尾
	LDA	CURLIN+1
	CMP	LINNUM+1
	BCS	LUK4IT
	TYA
	SEC
	ADC	TXTPTR
	LDX	TXTPTR+1
	BCC	LUKALL
	INX
	BCSA	LUKALL		;ALWAYS GOES. ; 总是跳转
LUK4IT: LDWX	TXTTAB
LUKALL: JSR	FNDLNC		;[X,A] ARE ALL SET UP. ; [X,A]已全部设置好
QFOUND: BCC	USERR		;GOTO LINE IS NONEXISTANT. ; GOTO行不存在
	LDA	LOWTR
	SBCI	1
	STA	TXTPTR
	LDA	LOWTR+1
	SBCI	0
	STA	TXTPTR+1
GORTS:	RTS			;PROCESS THE STATEMENT. ; 处理语句
;
; "RETURN" RESTORES THE LINE NUMBER AND TEXT PNTR FROM THE STACK ; "RETURN"从堆栈恢复行号和文本指针
; AND ELIMINATES ALL THE "FOR" ENTRIES IN FRONT OF THE "GOSUB" ENTRY. ; 并消除"GOSUB"条目前的所有"FOR"条目
;
RETURN: BNE	GORTS		;NO TERMINATOR=BLOW HIM UP. ; 无终止符=让他爆炸
	LDAI	255
	STA	FORPNT+1	;MAKE SURE THE VARIABLE'S PNTR ; 确保变量的指针
				;NEVER GETS MATCHED. ; 永远不会被匹配
	JSR	FNDFOR		;GO PAST ALL THE "FOR" ENTRIES. ; 经过所有"FOR"条目
	TXS
	CMPI	GOSUTK		;RETURN WITHOUT GOSUB? ; 没有GOSUB返回？
	BEQ	RETU1
	LDXI	ERRRG
	SKIP2
USERR:	LDXI	ERRUS		;NO MATCH SO "US" ERROR. ; 不匹配所以"US"错误
	JMP	ERROR		;YES. ; 是
SNERR2: JMP	SNERR
RETU1:	PLA			;REMOVE GOSUTK. ; 移除GOSUTK
	PULWD	CURLIN		;GET LINE NUMBER "GOSUB" WAS FROM. ; 获取"GOSUB"来自的行号
	PULWD	TXTPTR		;GET TEXT PNTR FROM "GOSUB". ; 从"GOSUB"获取文本指针
DATA:	JSR	DATAN		;SKIP TO END OF STATEMENT, ; 跳到语句结尾，
				;SINCE WHEN "GOSUB" STUCK THE TEXT  PNTR ; 因为当"GOSUB"粘贴文本指针时
				;ONTO THE STACK, THE LINE NUMBER ARG ; 到堆栈上时，行号参数
				;HADN'T BEEN READ YET. ; 尚未被读取
ADDON:	TYA
	CLC
	ADC	TXTPTR
	STA	TXTPTR
	BCC	REMRTS
	INC	TXTPTR+1
REMRTS: RTS			;"NEWSTT" RTS ADDR IS STILL THERE. ; "NEWSTT" RTS地址仍在

DATAN:	LDXI	":"		;"DATA" TERMINATES ON ":" AND NULL. ; "DATA"以":"和空终止
	SKIP2
REMN:	LDXI	0		;THE ONLY TERMINATOR IS NULL. ; 唯一终止符是空
	STX	CHARAC		;PRESERVE IT. ; 保存它
	LDYI	0		;THIS MAKES CHARAC=0 AFTER SWAP. ; 这使交换后CHARAC=0
	STY	ENDCHR
EXCHQT: LDA	ENDCHR
	LDX	CHARAC
	STA	CHARAC
	STX	ENDCHR
REMER:	LDADY	TXTPTR
	BEQ	REMRTS		;NULL ALWAYS TERMINATES. ; 空总是终止
	CMP	ENDCHR		;IS IT THE OTHER TERMINATOR? ; 是另一个终止符吗？
	BEQ	REMRTS		;YES, IT'S FINISHED. ; 是，已完成
	INY			;PROGRESS TO NEXT CHARACTER. ; 前进到下一个字符
	CMPI	34		;IS IT A QUOTE? ; 是引号吗？
	BNE	REMER		;NO, JUST CONTINUE. ; 否，继续
	BEQA	EXCHQT		;YES, TIME TO TRADE. ; 是，交换时间
PAGE
SUBTTL	"IF ... THEN" CODE. ; "IF ... THEN"代码
IF:	JSR	FRMEVL		;EVALUATE A FORMULA. ; 评估公式
	JSR	CHRGOT		;GET CURRENT CHARACTER. ; 获取当前字符
	CMPI	GOTOTK		;IS TERMINATING CHARACTER A GOTOTK? ; 终止字符是GOTOTK吗？
	BEQ	OKGOTO		;YES. ; 是
	SYNCHK	THENTK		;NO, IT MUST BE "THEN". ; 否，必须是"THEN"
OKGOTO: LDA	FACEXP		;0=FALSE. ALL OTHERS TRUE. ; 0=假。所有其他为真
	BNE	DOCOND		;TRUE ! ; 真！
REM:	JSR	REMN		;SKIP REST OF STATEMENT. ; 跳过语句的其余部分
	BEQA	ADDON		;WILL ALWAYS BRANCH. ; 总是分支
DOCOND: JSR	CHRGOT		;TEST CURRENT CHARACTER. ; 测试当前字符
	BCS	DOCO		;IF A NUMBER, GOTO IT. ; 如果是数字，GOTO它
	JMP	GOTO
DOCO:	JMP	GONE3		;INTERPRET NEW STATEMENT. ; 解释新语句
PAGE
SUBTTL	"ON ... GO TO ..." CODE. ; "ON ... GO TO ..."代码
ONGOTO: JSR	GETBYT		;GET VALUE IN FACLO. ; 获取FACLO中的值
	PHA			;SAVE FOR LATER. ; 保存以备后用
	CMPI	GOSUTK		;AN "ON ... GOSUB" PERHAPS? ; 可能是"ON ... GOSUB"吗？
	BEQ	ONGLOP		;YES. ; 是
SNERR3: CMPI	GOTOTK		;MUST BE "GOTOTK". ; 必须是"GOTOTK"
	BNE	SNERR2
ONGLOP: DEC	FACLO
	BNE	ONGLP1		;SKIP ANOTHER LINE NUMBER. ; 跳过另一个行号
	PLA			;GET DISPATCH CHARACTER. ; 获取分发字符
	JMP	GONE2
ONGLP1: JSR	CHRGET		;ADVANCE AND SET CODES. ; 前进并设置代码
	JSR	LINGET
	CMPI	44		;IS IT A COMMA? ; 是逗号吗？
	BEQ	ONGLOP
	PLA			;REMOVE STACK ENTRY (TOKEN). ; 移除堆栈条目（令牌）
ONGRTS: RTS			;EITHER END-OF-LINE OR SYNTAX ERROR. ; 要么行结束要么语法错误
PAGE
SUBTTL	LINGET -- READ A LINE NUMBER INTO LINNUM ; LINGET -- 读取行号到LINNUM
;
; "LINGET" READS A LINE NUMBER FROM THE CURRENT TEXT POSITION. ; "LINGET"从当前文本位置读取行号
;
; LINE NUMBERS RANGE FROM 0 TO 64000-1. ; 行号范围从0到64000-1
;
; THE ANSWER IS RETURNED IN "LINNUM". ; 答案在"LINNUM"中返回
; "TXTPTR" IS UPDATED TO POINT TO THE TERMINATING CHARCTER ; "TXTPTR"更新为指向终止字符
; AND [A] = THE TERMINATING CHARACTER WITH CONDITION ; 并且[A] = 带有条件代码设置的终止字符
; CODES SET UP TO REFLECT ITS VALUE. ; 反映其值
;
LINGET: LDXI	0
	STX	LINNUM		;INITIALIZE LINE NUMBER TO ZERO. ; 初始化行号为0
	STX	LINNUM+1
MORLIN: BCS	ONGRTS		;IT IS NOT A DIGIT. ; 不是数字
	SBCI	"0"-1		;-1 SINCE C=0. ; -1因为C=0
	STA	CHARAC		;SAVE CHARACTER. ; 保存字符
	LDA	LINNUM+1
	STA	INDEX
	CMPI	25		;LINE NUMBER WILL BE .LT. 64000? ; 行号将小于64000吗？
	BCS	SNERR3
	LDA	LINNUM
	ASL	A,		;MULTIPLY BY 10. ; 乘以10
	ROL	INDEX
	ASL	A
	ROL	INDEX
	ADC	LINNUM
	STA	LINNUM
	LDA	INDEX
	ADC	LINNUM+1
	STA	LINNUM+1
	ASL	LINNUM
	ROL	LINNUM+1
	LDA	LINNUM
	ADC	CHARAC		;ADD IN DIGIT. ; 加入数字
	STA	LINNUM
	BCC	NXTLGC
	INC	LINNUM+1
NXTLGC: JSR	CHRGET
	JMP	MORLIN

PAGE
SUBTTL	"LET" CODE. ; "LET"代码
LET:	JSR	PTRGET		;GET PNTR TO VARIABLE INTO "VARPNT". ; 获取指向变量的指针到"VARPNT"
	STWD	FORPNT		;PRESERVE POINTER. ; 保存指针
	SYNCHK	EQULTK		;"=" IS NECESSARY. ; "=" 是必需的
IFN	INTPRC,<
	LDA	INTFLG		;SAVE FOR LATER. ; 保存供后续使用
	PHA>
	LDA	VALTYP		;RETAIN THE VARIABLE'S VALUE TYPE. ; 保留变量的值类型
	PHA
	JSR	FRMEVL		;GET VALUE OF FORMULA INTO "FAC". ; 将公式的值获取到 "FAC"
	PLA
	ROL	A,		;CARRY SET FOR STRING, OFF FOR ; 对于字符串设置进位，对于数字清除进位
				;NUMERIC.
	JSR	CHKVAL		;MAKE SURE "VALTYP" MATCHES CARRY. ; 确保 "VALTYP" 与进位匹配
				;AND SET ZERO FLAG FOR NUMERIC. ; 并为数字设置零标志
	BNE	COPSTR		;IF NUMERIC, COPY IT. ; 如果是数字，则复制它
COPNUM:
IFN	INTPRC,<
	PLA			;GET NUMBER TYPE. ; 获取数字类型
QINTGR: BPL	COPFLT		;STORE A FLTING NUMBER. ; 存储浮点数
	JSR	ROUND		;ROUND INTEGER. ; 舍入整数
	JSR	AYINT		;MAKE 2-BYTE NUMBER. ; 制作2字节数字
	LDYI	0
	LDA	FACMO		;GET HIGH. ; 获取高位
	STADY	FORPNT		;STORE IT. ; 存储它
	INY
	LDA	FACLO		;GET LOW. ; 获取低位
	STADY	FORPNT
	RTS>
COPFLT: JMP	MOVVF		;PUT NUMBER @FORPNT. ; 将数字放入 @FORPNT

COPSTR:
IFN	INTPRC,<PLA>		;IF STRING, NO INTFLG. ; 如果是字符串，则没有 INTFLG
INPCOM:
IFN	TIME,<
	LDY	FORPNT+1	;TI$? ; 是 TI$ 吗？
	CPYI	ZERO/256	;ONLY TI$ CAN BE THIS ON ASSIG. ; 只有 TI$ 在赋值时可以是这个
	BNE	GETSPT		; WAS NOT TI$. ; 不是 TI$
	JSR	FREFAC		;WE WONT NEEDIT. ; 我们不需要它
	CMPI	6		;LENGTH CORRECT? ; 长度正确吗？
	BNE	FCERR2
	LDYI	0		;YES. DO SETUP. ; 是的，进行设置
	STY	FACEXP		;ZERO FAC TO START WITH. ; 首先将 FAC 清零
	STY	FACSGN
TIMELP: STY	FBUFPT		;SAVE POSOTION. ; 保存位置
	JSR	TIMNUM		;GET A DIGIT. ; 获取一个数字
	JSR	MUL10		;WHOLE QTY BY 10. ; 整体数量乘以 10
	INC	FBUFPT
	LDY	FBUFPT
	JSR	TIMNUM
	JSR	MOVAF
	TAX			;IF NUM=0 THEN NO MULT. ; 如果数字=0则不乘
	BEQ	NOML6		;IF =0, GO TIT. ; 如果等于0，则跳转
	INX			;MULT BY TWO. ; 乘以二
	TXA
	JSR	FINML6		;ADD IN AND MULT BY 2 GIVES *6. ; 加入并乘以2得到*6
NOML6:	LDY	FBUFPT
	INY
	CPYI	6		;DONE ALL SIX? ; 完成所有六个了吗？
	BNE	TIMELP
	JSR	MUL10		;ONE LAST TIME. ; 最后一次
	JSR	QINT		;SHIFT IT OVER TO THE RIGHT. ; 将其向右移位
	LDXI	2
	SEI			;DISALLOW INTERRUPTS. ; 禁止中断
TIMEST: LDA	FACMOH,X
	STA	CQTIMR,X
	DEX
	BPL	TIMEST		;LOOP 3 TIMES. ; 循环3次
	CLI			;TURN ON INTS AGAIN. ; 再次开启中断
	RTS
TIMNUM: LDADY	INDEX		;INDEX SET UP BY FREFAC. ; 索引由 FREFAC 设置
	JSR	QNUM
	BCC	GOTNUM
FCERR2: JMP	FCERR		;MUST BE NUMERIC STRING. ; 必须是数字字符串
GOTNUM: SBCI	"0"-1		;C IS OFF. ; C 是关闭的
	JMP	FINLOG>		;ADD IN DIGIT TO FAC. ; 将数字加入 FAC

GETSPT: LDYI	2		;GET PNTR TO DESCRIPTOR. ; 获取指向描述符的指针
	LDADY	FACMO
	CMP	FRETOP+1	;SEE IF IT POINTS INTO STRING SPACE. ; 查看它是否指向字符串空间
	BCC	DNTCPY		;IF [FRETOP],GT.[2&3,FACMO], DON'T COPY. ; 如果 [FRETOP] > [2&3,FACMO]，则不复制
	BNE	QVARIA		;IT IS LESS. ; 它较小
	DEY
	LDADY	FACMO
	CMP	FRETOP		;COMPARE LOW ORDERS. ; 比较低位
	BCC	DNTCPY
QVARIA: LDY	FACLO
	CPY	VARTAB+1	;IF [VARTAB].GT.[FACMO], DON'T COPY. ; 如果 [VARTAB] > [FACMO]，则不复制
	BCC	DNTCPY
	BNE	COPY		;IT IS LESS. ; 它较小
	LDA	FACMO
	CMP	VARTAB		;COMPARE LOW ORDERS. ; 比较低位
	BCS	COPY
DNTCPY: LDWD	FACMO
	JMP	COPYZC
COPY:	LDYI	0
	LDADY	FACMO
	JSR	STRINI		;GET ROOM TO COPY STRING INTO. ; 获取空间以复制字符串
	LDWD	DSCPNT		;GET POINTER TO OLD DESCRIPTOR, SO ; 获取指向旧描述符的指针，以便
	STWD	STRNG1		;MOVINS CAN FIND STRING. ; MOVINS 可以找到字符串
	JSR	MOVINS		;COPY IT. ; 复制它
	LDWDI	DSCTMP		;GET POINTER TO OLD DESCRIPTOR. ; 获取指向旧描述符的指针
COPYZC: STWD	DSCPNT		;REMEMBER POINTER TO DESCRIPTOR. ; 记住指向描述符的指针
	JSR	FRETMS		;FREE UP THE TEMPORARY WITHOUT ; 释放临时变量，而不
				;FREEING UP ANY STRING SPACE. ; 释放任何字符串空间
	LDYI	0
	LDADY	DSCPNT
	STADY	FORPNT
	INY			;POINT TO STRING PNTR. ; 指向字符串指针
	LDADY	DSCPNT
	STADY	FORPNT
	INY
	LDADY	DSCPNT
	STADY	FORPNT
	RTS
PAGE
SUBTTL	PRINT CODE. ; PRINT 代码
IFN	EXTIO,<
PRINTN: JSR	CMD		;DOCMD ; 执行CMD
	JMP	IODONE		;RELEASE CHANNEL. ; 释放通道
CMD:	JSR	GETBYT
	BEQ	SAVEIT
	SYNCHK	44		;COMMA? ; 逗号？
SAVEIT: PHP
	JSR	CQOOUT		;CHECK AND OPEN OUTPUT CHANNL. ; 检查并打开输出通道
	STX	CHANNL		;CHANNL TO OUTPUT ON. ; 要输出的通道
	PLP			;GET STATUS BACK. ; 取回状态
	JMP	PRINT>
STRDON: JSR	STRPRT
NEWCHR: JSR	CHRGOT		;REGET LAST CHARACTER. ; 重新获取最后一个字符
PRINT:	BEQ	CRDO		;TERMINATOR SO TYPE CRLF. ; 终止符，所以打印回车换行
PRINTC: BEQ	PRTRTS		;HERE AFTER SEEING TAB(X) OR , OR ; ; 在看到 TAB(X) 或 , 或 ; 之后来到这里
				;IN WHICH CASE A TERMINATOR DOES NOT ; 在这种情况下，终止符并不
				;MEAN TYPE A CRLF BUT JUST RTS. ; 意味着打印回车换行，而只是 RTS
	CMPI	TABTK		;TAB FUNCTION? ; TAB 函数？
	BEQ	TABER		;YES. ; 是
	CMPI	SPCTK		;SPACE FUNCTION? ; SPACE 函数？
	CLC
	BEQ	TABER
	CMPI	44		;A COMMA? ; 逗号？
	BEQ	COMPRT		;YES. ; 是
	CMPI	59		;A SEMICOLON? ; 分号？
	BEQ	NOTABR		;YES. ; 是
	JSR	FRMEVL		;EVALUATE THE FORMULA. ; 计算公式
	BIT	VALTYP		;A STRING? ; 字符串？
	BMI	STRDON		;YES. ; 是
	JSR	FOUT
	JSR	STRLIT		;BUILD DESCRIPTOR. ; 构建描述符
IFN	REALIO-3,<
	LDYI	0		;GET THE POINTER. ; 获取指针
	LDADY	FACMO
	CLC
	ADC	TRMPOS		;MAKE SURE LEN+POS.LT.WIDTH. ; 确保长度+位置 < 宽度
	CMP	LINWID		;GREATER THAN LINE LENGTH? ; 大于行长度吗？
				;REMEMBER SPACE PRINTED AFTER NUMBER. ; 记住数字后打印的空格
	BCC	LINCHK		;GO TYPE. ; 去打印
	JSR	CRDO>		;YES, TYPE CRLF FIRST. ; 是，先打印回车换行
LINCHK: JSR	STRPRT		;PRINT THE NUMBER. ; 打印数字
	JSR	OUTSPC		;PRINT A SPACE ; 打印一个空格
	BNEA	NEWCHR		;ALWAYS GOES. ; 总是跳转
IFN	REALIO-4,<
IFN	BUFPAG,<
FININL: LDAI	0
	STA	BUF,X
	LDXYI	BUF-1>
IFE	BUFPAG,<
FININL: LDYI	0		;PUT A ZERO AT END OF BUF. ; 在 BUF 末尾放一个零
	STY	BUF,X
	LDXI	BUF-1>		;SETUP POINTER. ; 设置指针
IFN	EXTIO,<
	LDA	CHANNL		;NO CRDO IF NOT TERMINAL. ; 如果不是终端，则不执行 CRDO
	BNE	PRTRTS>>
CRDO:
IFE	EXTIO,<
	LDAI	13		;MAKE TRMPOS LESS THAN LINE LENGTH. ; 使 TRMPOS 小于行长度
	STA	TRMPOS>
IFN	EXTIO,<
IFN	REALIO-3,<
	LDA	CHANNL
	BNE	GOCR
	STA	TRMPOS>
GOCR:	LDAI	13>		;X AND Y MUST BE PRESERVED. ; X 和 Y 必须保留
	JSR	OUTDO
	LDAI	10
	JSR	OUTDO
CRFIN:
IFN	EXTIO,<
IFN	REALIO-3,<
	LDA	CHANNL
	BNE	PRTRTS>>
IFE	NULCMD,<
IFN	REALIO-3,<
	LDAI	0
	STA	TRMPOS>
	EORI	255>
IFN	NULCMD,<
	TXA			;PRESERVE [ACCX]. SOME NEED IT. ; 保留 [ACCX]。有些需要它
	PHA
	LDX	NULCNT		;GET NUMBER OF NULLS. ; 获取空字符数
	BEQ	CLRPOS
	LDAI	0
PRTNUL: JSR	OUTDO
	DEX			;DONE WITH NULLS? ; 空字符完成了吗？
	BNE	PRTNUL
CLRPOS: STX	TRMPOS
	PLA
	TAX>
PRTRTS: RTS

COMPRT: LDA	TRMPOS
NCMPOS==<<<LINLEN/CLMWID>-1>*CLMWID>	;CLMWID BEYOND WHICH THERE ARE ; CLMWID 超出后就没有
IFN	REALIO-3,<
				;NO MORE COMMA FIELDS. ; 更多的逗号字段了
	CMP	NCMWID		;SO ALL COMMA DOES IS "CRDO". ; 所以所有逗号的作用就是 "CRDO"

	BCC	MORCOM
	JSR	CRDO		;TYPE CRLF. ; 打印回车换行
	JMP	NOTABR>		;AND QUIT IF BEYOND LAST FIELD. ; 如果超出最后一个字段则退出
MORCOM: SEC
MORCO1: SBCI	CLMWID		;GET [A] MODULUS CLMWID. ; 获取 [A] 对 CLMWID 取模
	BCS	MORCO1
	EORI	255		;FILL PRINT POS OUT TO EVEN CLMWID SO ; 将打印位置填充到偶数 CLMWID，以便
	ADCI	1
	BNE	ASPAC		;PRINT [A] SPACES. ; 打印 [A] 个空格

TABER:	PHP			;REMEMBER IF SPC OR TAB FUNCTION. ; 记住是 SPC 还是 TAB 函数
	JSR	GTBYTC		;GET VALUE INTO ACCX. ; 获取值到 ACCX
	CMPI	41
	BNE	SNERR4
	PLP
	BCC	XSPAC		;PRINT [X] SPACES. ; 打印 [X] 个空格
	TXA
	SBC	TRMPOS
	BCC	NOTABR		;NEGATIVE, DON'T PRINT ANY. ; 负数，不打印任何内容
ASPAC:	TAX
XSPAC:	INX
XSPAC2: DEX			;DECREMENT THE COUNT. ; 递减计数
	BNE	XSPAC1
NOTABR: JSR	CHRGET		;REGET LAST CHARACTER. ; 重新获取最后一个字符
	JMP	PRINTC		;DON'T CALL CRDO. ; 不调用 CRDO
XSPAC1: JSR	OUTSPC
	BNEA	XSPAC2
;
; PRINT THE STRING POINTED TO BY [Y,A] WHICH ENDS WITH A ZERO. ; 打印由 [Y,A] 指向的以零结尾的字符串
; IF THE STRING IS BELOW DSCTMP IT WILL BE COPIED INTO STRING SPACE. ; 如果字符串在 DSCTMP 下方，它将被复制到字符串空间
;
STROUT: JSR	STRLIT		;GET A STRING LITERAL. ; 获取字符串字面量
;
; PRINT THE STRING WHOSE DESCRIPTOR IS POINTED TO BY FACMO. ; 打印其描述符由 FACMO 指向的字符串
;
STRPRT: JSR	FREFAC		;RETURN TEMP POINTER. ; 返回临时指针
	TAX			;PUT COUNT INTO COUNTER. ; 将计数放入计数器
	LDYI	0
	INX			;MOVE ONE AHEAD. ; 向前移动一个
STRPR2: DEX
	BEQ	PRTRTS		;ALL DONE. ; 全部完成
	LDADY	INDEX		;PNTR TO ACT STRNG SET BY FREFAC. ; 指向由 FREFAC 设置的实际字符串的指针
	JSR	OUTDO
	INY
	CMPI	13
	BNE	STRPR2
	JSR	CRFIN		;TYPE REST OF CARRIAGE RETURN. ; 打印回车符的剩余部分
	JMP	STRPR2		;AND ON AND ON. ; 如此继续
;
; OUTDO OUTPUTS THE CHARACTER IN ACCA, USING CNTWFL ; OUTDO 使用 CNTWFL 输出 ACCA 中的字符
; (SUPPRESS OR NOT), TRMPOS (PRINT HEAD POSITION), ; （抑制或不抑制），TRMPOS（打印头位置）
; TIMING, ETCQ. NO REGISTERS ARE CHANGED. ; 定时等。不更改任何寄存器
;
OUTSPC:
IFN	REALIO-3,<
	LDAI	" ">
IFE	REALIO-3,<
	LDA	CHANNL
	BEQ	CRTSKP
	LDAI	" "
	SKIP2
CRTSKP: LDAI	29>		;COMMODORE'S SKIP CHARACTER. ; Commodore 的跳过字符
	SKIP2
OUTQST: LDAI	"?"
OUTDO:	IFN	REALIO,<
	BIT	CNTWFL		;SHOULDN'T AFFECT CHANNEL I/O! ; 不应影响通道 I/O！
	BMI	OUTRTS>
IFN	REALIO-3,<
	PHA
	CMPI	32		;IS THIS A PRINTING CHAR? ; 这是一个可打印字符吗？
	BCC	TRYOUT		;NO, DON'T INCLUDE IT IN TRMPOS. ; 否，不将其包含在 TRMPOS 中
	LDA	TRMPOS
	CMP	LINWID		;LENGTH = TERMINAL WIDTH? ; 长度 = 终端宽度？
	BNE	OUTDO1
	JSR	CRDO		;YES, TYPE CRLF ; 是，打印回车换行
OUTDO1:
IFN EXTIO,<
	LDA	CHANNL
	BNE	TRYOUT>
INCTRM: INC	TRMPOS		;INCREMENT COUNT. ; 增加计数
TRYOUT: PLA>			;RESTORE THE A REGISTER ; 恢复 A 寄存器

IFE	REALIO-1,<
	STY	KIMY>		;PRESERVE Y. ; 保留 Y
IFE	REALIO-4,<ORAI	^O200>	;TURN ON B7 FOR APPLE. ; 为 Apple 开启 B7
IFN	REALIO,<
OUTLOC: JSR	OUTCH>		;OUTPUT THE CHARACTER. ; 输出字符
IFE	REALIO-1,<
	LDY	KIMY>		;GET Y BACK. ; 取回 Y
IFE	REALIO-2,<REPEAT	4,<NOP>>
IFE	REALIO-4,<ANDI	^O177>	;GET [A] BACK FROM APPLE. ; 从 Apple 取回 [A]

IFE	REALIO,<
	TJSR	OUTSIM##>	;CALL SIMULATOR OUTPUT ROUTINE ; 调用模拟器输出例程
OUTRTS: ANDI	255		;SET Z=0. ; 设置 Z=0
GETRTS: RTS

PAGE
SUBTTL	INPUT AND READ CODE. ; INPUT 和 READ 代码
;
; HERE WHEN THE DATA THAT WAS TYPED IN OR IN "DATA" STATEMENTS ; 当键入的数据或 "DATA" 语句中的数据
; IS IMPROPERLY FORMATTED. FOR "INPUT" WE START AGAIN. ; 格式不正确时来到这里。对于 "INPUT"，我们重新开始
; FOR "READ" WE GIVE A SYNTAX ERROR AT THE DATA LINE. ; 对于 "READ"，我们在数据行给出语法错误
;
TRMNOK: LDA	INPFLG
	BEQ	TRMNO1		;IF INPUT TRY AGAIN. ; 如果是 INPUT，重试
IFN	GETCMD,<
	BMI	GETDTL
	LDYI	255		;MAKE IT LOOK DIRECT. ; 使其看起来是直接的
	BNEA	STCURL		;ALWAYS GOES. ; 总是跳转
GETDTL:>
	LDWD	DATLIN		;GET DATA LINE NUMBER. ; 获取数据行号
STCURL: STWD	CURLIN		;MAKE IT CURRENT LINE. ; 使其成为当前行
SNERR4: JMP	SNERR
TRMNO1:
IFN	EXTIO,<
	LDA	CHANNL		;IF NOT TERMINAL, GIVE BAD DATA. ; 如果不是终端，给出错误数据
	BEQ	DOAGIN
	LDXI	ERRBD
	JMP	ERROR>
DOAGIN: LDWDI	TRYAGN
	JSR	STROUT		;PRINT "?REDO FROM START". ; 打印 "?REDO FROM START"
	LDWD	OLDTXT		;POINT AT START ; 指向开始
	STWD	TXTPTR		;OF THIS CURRENT LINE. ; 当前行的
	RTS			;GO TO "NEWSTT". ; 转到 "NEWSTT"
IFN	GETCMD,<
GET:	JSR	ERRDIR		;DIRECT IS NOT OK. ; 直接模式不行
IFN	EXTIO,<
	CMPI	"#"		;SEE IF "GET#". ; 查看是否是 "GET#"
	BNE	GETTTY		;NO, JUST GET TTY INPUT. ; 否，仅获取 TTY 输入
	JSR	CHRGET		;MOVE UP TO NEXT BYTE. ; 移动到下一个字节
	JSR	GETBYT		;GET CHANNEL INTO X ; 获取通道到 X
	SYNCHK	44		;COMMA? ; 逗号？
	JSR	CQOIN		;GET CHANNEL OPEN FOR INPUT. ; 打开通道以供输入
	STX	CHANNL>
GETTTY: LDXYI	BUF+1		;POINT TO 0. ; 指向 0
IFN	BUFPAG,<
	LDAI	0		;TO STUFF AND TO POINT. ; 用于填充和指向
	STA	BUF+1>
IFE	BUFPAG,<
	STY	BUF+1>		;ZERO IT. ; 将其清零
	LDAI	64		;TURN ON V-BIT. ; 开启 V 位
	JSR	INPCO1		;DO THE GET. ; 执行 GET
IFN	EXTIO,<
	LDX	CHANNL
	BNE	IORELE>		;RELEASE. ; 释放
	RTS>

IFN	EXTIO,<
INPUTN: JSR	GETBYT		;GET CHANNEL NUMBER. ; 获取通道号
	SYNCHK	44		;A COMMA? ; 逗号？
	JSR	CQOIN		;GO WHERE COMMODORE CHECKS IN OPEN. ; 转到 Commodore 检查打开的地方
	STX	CHANNL
	JSR	NOTQTI		;DO INPUT TO VARIABLES. ; 对变量进行 INPUT
IODONE: LDA	CHANNL		;RELEASE CHANNEL. ; 释放通道
IORELE: JSR	CQCCHN
	LDXI	0		;RESET CHANNEL TO TERMINAL. ; 将通道重置为终端
	STX	CHANNL
	RTS>
INPUT:	IFN	REALIO,<
	LSR	CNTWFL>		;BE TALKATIVE. ; 健谈
	CMPI	34		;A QUOTE? ; 引号？
	BNE	NOTQTI		;NO MESSAGE. ; 无消息
	JSR	STRTXT		;LITERALIZE THE STRING IN TEXT ; 将文本中的字符串字面化
	SYNCHK	59		;MUST END WITH SEMICOLON. ; 必须以分号结尾
	JSR	STRPRT		;PRINT IT OUT. ; 打印出来
NOTQTI: JSR	ERRDIR		;USE COMMON ROUTINE SINCE DEF DIRECT ; 使用通用例程，因为 DEF 直接模式
	LDAI	44		;GET COMMA. ; 获取逗号
	STA	BUF-1
				;IS ALSO ILLEGAL. ; 也是非法的
GETAGN: JSR	QINLIN		;TYPE "?" AND INPUT A LINE OF TEXT. ; 打印 "?" 并输入一行文本
IFN	EXTIO,<
	LDA	CHANNL
	BEQ	BUFFUL
	LDA	CQSTAT		;GET STATUS BYTE. ; 获取状态字节
	ANDI	2
	BEQ	BUFFUL		;A-OK. ; 好的
	JSR	IODONE		;BAD. CLOSE CHANNEL. ; 坏的，关闭通道
	JMP	DATA		;SKIP REST OF INPUT. ; 跳过输入的其余部分
BUFFUL:>
	LDA	BUF		;ANYTHING INPUT? ; 有输入任何内容吗？
	BNE	INPCON		;YES, CONTINUE. ; 是，继续
IFN	EXTIO,<
	LDA	CHANNL		;BLANK LINE MEANS GET ANOTHER. ; 空行意味着获取另一个
	BNE	GETAGN>		;IF NOT TERMINAL. ; 如果不是终端
	CLC			;MAKE SURE DONT PRINT BREAK ; 确保不打印 BREAK
	JMP	STPEND		;NO, STOP. ; 否，停止
QINLIN:
IFN	EXTIO,<
	LDA	CHANNL
	BNE	GINLIN>
	JSR	OUTQST
	JSR	OUTSPC
GINLIN: JMP	INLIN
READ:	LDXY	DATPTR		;GET LAST DATA LOCATION. ; 获取最后的数据位置
	XWD	^O1000,^O251	;LDAI TYA TO MAKE IT NONZERO. ; LDAI TYA 使其非零
IFE	BUFPAG,<
INPCON: >
	TYA
IFN	BUFPAG,<
	SKIP2
INPCON: LDAI	0>		;SET FLAG THAT THIS IS INPUT ; 设置标志表明这是 INPUT
INPCO1: STA	INPFLG		;STORE THE FLAG. ; 存储标志
;
; IN THE PROCESSING OF DATA AND READ STATEMENTS: ; 在处理 DATA 和 READ 语句时：
; ONE POINTER POINTS TO THE DATA (IE, THE NUMBERS BEING FETCHED) ; 一个指针指向数据（即正在获取的数字）
; AND ANOTHER POINTS TO THE LIST OF VARIABLES. ; 另一个指针指向变量列表
;
; THE POINTER INTO THE DATA ALWAYS STARTS POINTING TO A ; 指向数据的指针总是起始于指向一个
; TERMINATOR -- A , : OR END-OF-LINE. ; 终止符——一个逗号、冒号或行结束符
;
; AT THIS POINT TXTPTR POINTS TO LIST OF VARIABLES AND ; 此时 TXTPTR 指向变量列表
; [Y,X] POINTS TO DATA OR INPUT LINE. ; [Y,X] 指向数据或输入行
;
	STXY	INPPTR
INLOOP: JSR	PTRGET		;READ VARIABLE LIST. ; 读取变量列表
	STWD	FORPNT		;SAVE POINTER FOR "LET" STRING STUFFING. ; 保存指针以供 "LET" 字符串填充使用
				;RETURNS PNTR TOP VAR IN VARPNT. ; 返回指向VARPNT中变量的指针
	LDWD	TXTPTR		;SAVE TEXT PNTR. ; 保存文本指针
	STWD	VARTXT
	LDXY	INPPTR
	STXY	TXTPTR
	JSR	CHRGOT		;GET IT AND SET Z IF TERM. ; 获取它并在终止时设置Z
	BNE	DATBK1
	BIT	INPFLG
IFN	GETCMD,<
	BVC	QDATA
	JSR	CZGETL		;DON'T WANT INCHR. JUST ONE. ; 不想要INCHR，只要一个
IFE	REALIO-4,<
	ANDI	127>
	STA	BUF		;MAKE IT FIRST CHARACTER. ; 使其成为第一个字符
	LDXYI	<BUF-1>		;POINT JUST BEFORE IT. ; 指向它之前
IFE	BUFPAG,<
	BEQA	DATBK>
IFN	BUFPAG,<
	BNEA	DATBK>>		;GO PROCESS. ; 去处理
QDATA:	BMI	DATLOP		;SEARCH FOR ANOTHER DATA STATEMENT. ; 搜索另一个DATA语句
IFN	EXTIO,<
	LDA	CHANNL
	BNE	GETNTH>
	JSR	OUTQST
GETNTH: JSR	QINLIN		;GET ANOTHER LINE. ; 获取另一行
DATBK:	STXY	TXTPTR		;SET FOR "CHRGET". ; 为"CHRGET"设置
DATBK1: JSR	CHRGET
	BIT	VALTYP		;GET VALUE TYPE. ; 获取值类型
	BPL	NUMINS		;INPUT A NUMBER IF NUMERIC. ; 如果是数字则输入数字
IFN	GETCMD,<
	BIT	INPFLG		;GET? ; GET？
	BVC	SETQUT		;NO, GO SET QUOTE. ; 否，去设置引号
	INX
	STX	TXTPTR
	LDAI	0		;ZERO TERMINATORS. ; 零终止符
	STA	CHARAC
	BEQA	RESETC>
SETQUT: STA	CHARAC		;ASSUME QUOTED STRING. ; 假定为引号字符串
	CMPI	34		;TERMINATORS OK? ; 终止符好吗？
	BEQ	NOWGET		;YES. ; 是
	LDAI	":"		;SET TERMINATORS TO ":" AND ; 设置终止符为":"和
	STA	CHARAC
	LDAI	44		;COMMA. ; 逗号
RESETC: CLC
NOWGET: STA	ENDCHR
	LDWD	TXTPTR
	ADCI	0		;C IS SET PROPERLY ABOVE. ; C在上面正确设置
	BCC	NOWGE1
	INY
NOWGE1: JSR	STRLT2		;MAKE A STRING DESCRIPTOR FOR THE VALUE ; 为值创建字符串描述符
				;AND COPY IF NECESSARY. ; 并在必要时复制
	JSR	ST2TXT		;SET TEXT POINTER. ; 设置文本指针
	JSR	INPCOM		;DO ASSIGNMENT. ; 进行赋值
	JMP	STRDN2
NUMINS: JSR	FIN
IFE	INTPRC,<
	JSR	MOVVF>
IFN	INTPRC,<
	LDA	INTFLG		;SET CODES ON FLAG. ; 在标志上设置代码
	JSR	QINTGR>		;GO DECIDE ON FLOAT. ; 去决定浮点
STRDN2: JSR	CHRGOT		;READ LAST CHARACTER. ; 读取最后一个字符
	BEQ	TRMOK		;":" OR EOL IS OK. ; ":"或EOL可以
	CMPI	44		;A COMMA? ; 逗号吗？
	JNE	TRMNOK
TRMOK:	LDWD	TXTPTR
	STWD	INPPTR		;SAVE FOR MORE READS. ; 保存以备更多读取
	LDWD	VARTXT
	STWD	TXTPTR		;POINT TO VARIABLE LIST. ; 指向变量列表
	JSR	CHRGOT		;LOOK AT LAST VARIABLE LIST CHARACTER. ; 查看最后一个变量列表字符
	BEQ	VAREND		;THAT'S THE END OF THE LIST. ; 那是列表的结尾
	JSR	CHKCOM		;NOT END. CHECK FOR COMMA. ; 未结束，检查逗号
	JMP	INLOOP
;
; SUBROUTINE TO FIND DATA ; 子程序用于查找DATA语句
; THE SEARCH IS MADE BY USING THE EXECUTION CODE FOR DATA TO ; 通过使用DATA的执行代码跳过语句来实现搜索
; SKIP OVER STATEMENTS. THE START WORD OF EACH STATEMENT ; 每个语句的起始字与"DATATK"比较
; IS COMPARED WITH "DATATK". EACH NEW LINE NUMBER ; 每个新行号存储在"DATLIN"中，以便在读取数据时
; IS STORED IN "DATLIN" SO THAT IF AN ERROR OCCURS ; 如果发生错误，错误消息可以给出格式错误数据的行号
; WHILE READING DATA THE ERROR MESSAGE CAN GIVE THE LINE
; NUMBER OF THE ILL-FORMATTED DATA.
;
DATLOP: JSR	DATAN		;SKIP SOME TEXT. ; 跳过一些文本
	INY                     ; Y寄存器加1
	TAX			;END OF LINE? ; 是否行结束?
	BNE	NOWLIN		;SHO AIN'T. ; 如果不是，跳转到NOWLIN
	LDXI	ERROD		;YES = "NO DATA" ERROR. ; 是，加载"无数据"错误码
	INY                     ; Y寄存器加1
	LDADY	TXTPTR          ; 加载TXTPTR指向的字符
	BEQ	ERRGO5          ; 如果为零，跳转到ERRGO5
	INY                     ; Y寄存器加1
	LDADY	TXTPTR		;GET HIGH BYTE OF LINE NUMBER. ; 获取行号的高字节
	STA	DATLIN          ; 存储到DATLIN
	INY                     ; Y寄存器加1
	LDADY	TXTPTR		;GET LOW BYTE. ; 获取行号的低字节
	INY                     ; Y寄存器加1
	STA	DATLIN+1        ; 存储到DATLIN+1
NOWLIN: LDADY	TXTPTR		;HOW IS IT? ; 获取当前字符
	TAX                     ; 传输到X寄存器
	JSR	ADDON		;ADD [Y] TO [TXTPTR]. ; 将Y加到TXTPTR
	CPXI	DATATK		;IS IT A "DATA" STATEMENT. ; 是否是"DATA"语句标记
	BNE	DATLOP		;NOT QUITE RIGHT. KEEP LOOKING. ; 不匹配，继续查找
	JMP	DATBK1		;THIS IS THE ONE ! ; 找到，跳转到DATBK1
VAREND: LDWD	INPPTR		;PUT AWAY A NEW DATA PNTR MAYBE. ; 可能保存新的数据指针
	LDX	INPFLG          ; 加载输入标志
	BPL	VARY0           ; 如果为正，跳转到VARY0
	JMP	RESFIN          ; 跳转到RESFIN
VARY0:	LDYI	0               ; Y寄存器清零
	LDADY	INPPTR		;LAST DATA CHR COULD HAVE BEEN ; 最后一个数据字符可能是
				;COMMA OR COLON BUT SHOULD BE NULL. ; 逗号或冒号，但应为空
	BEQ	INPRTS		;IT IS NULL. ; 如果是空，跳转到INPRTS
IFN	EXTIO,<                 ; 如果定义了扩展IO
	LDA	CHANNL		;IF NOT TERMINAL, NO TYPE. ; 如果不是终端，不显示
	BNE	INPRTS>         ; 跳转到INPRTS
	LDWDI	EXIGNT          ; 加载"EXTRA IGNORED"消息地址
	JMP	STROUT		;TYPE "?EXTRA IGNORED" ; 显示"?EXTRA IGNORED"
INPRTS: RTS			;DO NEXT STATEMENT. ; 执行下一条语句
EXIGNT: DT"?EXTRA IGNORED"    ; 定义文本"?EXTRA IGNORED"
	ACRLF                   ; 回车换行
	0                       ; 结束标志
TRYAGN: DT"?REDO FROM START"  ; 定义文本"?REDO FROM START"
	ACRLF                   ; 回车换行
	0                       ; 结束标志
PAGE                        ; 分页
SUBTTL	THE NEXT CODE IS THE "NEXT CODE" ; 子标题：下一段代码是"NEXT代码"
;
; A "FOR" ENTRY ON THE STACK HAS THE FOLLOWING FORMAT: ; 栈中的"FOR"条目具有以下格式：
;
; LOW ADDRESS ; 低地址
;	TOKEN (FORTK) 1 BYTE ;	标记(FORTK) 1字节
;	A POINTER TO THE LOOP VARIABLE 2 BYTES ;	指向循环变量的指针 2字节
;	THE STEP 4+ADDPRC BYTES ;	步长 4+ADDPRC字节
;	A BYTE REFLECTING THE SIGN OF THE INCREMENT 1 BYTE ;	反映增量符号的字节 1字节
;	THE UPPER VALUE (PACKED) 4+ADDPRC BYTES ;	上限值(打包) 4+ADDPRC字节
;	THE LINE NUMBER OF THE "FOR" STATEMENT 2 BYTES ;	"FOR"语句的行号 2字节
;	A TEXT POINTER INTO THE "FOR" STATEMENT 2 BYTES ;	指向"FOR"语句内部的文本指针 2字节
; HIGH ADDRESS ; 高地址
;
; TOTAL 16+2*ADDPRC BYTES. ; 总计 16+2*ADDPRC字节
;
NEXT:	BNE	GETFOR          ; 如果不为零，跳转到GETFOR
	LDYI	0		;WITHOUT ARG CALL "FNDFOR" WITH ; 无参数调用FNDFOR，设置
	BEQA	STXFOR		;[FORPNT]=0. ; FORPNT=0
GETFOR: JSR	PTRGET		;GET A POINTER TO LOOP VARIABLE ; 获取指向循环变量的指针
STXFOR: STWD	FORPNT		;INTO "FORPNT". ; 存储到FORPNT
	JSR	FNDFOR		;FIND THE MATCHING ENTRY IF ANY. ; 查找匹配的条目(如果有)
	BEQ	HAVFOR          ; 如果找到，跳转到HAVFOR
	LDXI	ERRNF		;"NEXT WITHOUT FOR". ; "NEXT没有对应的FOR"
ERRGO5: BEQ	ERRGO4          ; 跳转到ERRGO4
HAVFOR: TXS			;SETUP STACK. CHOP FIRST. ; 设置堆栈，首先调整
	TXA                     ; 传输X到A
	CLC                     ; 清除进位标志
	ADCI	4		;POINT TO INCREMENT ; 指向增量
	PHA			;SAVE THIS POINTER TO RESTORE TO [A] ; 保存此指针以便恢复到[A]
	ADCI	5+ADDPRC	;POINT TO UPPER LIMIT ; 指向上限
	STA	INDEX2		;SAVE AS INDEX ; 保存为索引
	PLA			;RESTORE POINTER TO INCREMENT ; 恢复指向增量的指针
	LDYI	1		;SET HI ADDR OF THING TO MOVE. ; 设置要移动内容的高地址
	JSR	MOVFM		;GET QUANTITY INTO THE FAC. ; 将数量获取到FAC
	TSX                     ; 传输堆栈指针到X
	LDA	257+7+ADDPRC,X, ;SET SIGN CORRECTLY. ; 正确设置符号
	STA	FACSGN          ; 存储到FACSGN
	LDWD	FORPNT          ; 加载FORPNT
	JSR	FADD		;ADD INC TO LOOP VARIABLE. ; 将增量加到循环变量
	JSR	MOVVF		;PACK THE FAC INTO MEMORY. ; 将FAC打包到内存
	LDYI	1               ; Y寄存器设为1
	JSR	FCOMPN		;COMPARE FAC WITH UPPER VALUE. ; 比较FAC与上限值
	TSX                     ; 传输堆栈指针到X
	SEC                     ; 设置进位标志
	SBC	257+7+ADDPRC,X, ;SUBTRACT SIGN OF INC FROM SIGN OF ; 从(FAC-终值)的符号中减去增量的符号
				;OF (CURRENT VALUE-FINAL VALUE). ; (当前值-终值)的符号
	BEQ	LOOPDN		;IF SIGN (FINAL-CURRENT)-SIGN STEP=0 ; 如果符号(终值-当前值)-符号步长=0
				;THEN LOOP IS DONE. ; 则循环完成
	LDA	2*ADDPRC+12+257,X ; 获取FOR语句的行号高字节
	STA	CURLIN		;STORE LINE NUMBER OF "FOR" STATEMENT. ; 存储FOR语句的行号
	LDA	257+13+<2*ADDPRC>,X ; 获取FOR语句的行号低字节
	STA	CURLIN+1        ; 存储到CURLIN+1
	LDA	2*ADDPRC+15+257,X ; 获取FOR语句的文本指针高字节
	STA	TXTPTR		;STORE TEXT PNTR INTO "FOR" STATEMENT. ; 存储指向FOR语句内部的文本指针
	LDA	2*ADDPRC+14+257,X ; 获取FOR语句的文本指针低字节
	STA	TXTPTR+1        ; 存储到TXTPTR+1
NEWSGO: JMP	NEWSTT		;PROCESS NEXT STATEMENT. ; 处理下一条语句
LOOPDN: TXA                     ; 传输X到A
	ADCI	2*ADDPRC+15		;ADDS 16 WITH CARRY. ; 带进位加16
	TAX                     ; 传输A到X
	TXS			;NEW STACK PNTR. ; 新的堆栈指针
	JSR	CHRGOT          ; 获取当前字符
	CMPI	44		;COMMA AT END? ; 末尾是逗号吗?
	BNE	NEWSGO          ; 不是，跳转到NEWSGO
	JSR	CHRGET          ; 获取下一个字符
	JSR	GETFOR		;DO NEXT BUT DON'T ALLOW BLANK VARIABLE ; 处理下一个但不允许空变量
				;PNTR. [VARPNT] IS THE STK PNTR WHICH ; 指针。[VARPNT]是堆栈指针
				;NEVER MATCHES ANY POINTER. ; 永远不会匹配任何指针
				;JSR TO PUT ON DUMMY NEWSTT ADDR. ; JSR以放置虚拟NEWSTT地址
SUBTTL FORMULA EVALUATION CODE. ; 子标题：公式求值代码
;
; THESE ROUTINES CHECK FOR CERTAIN "VALTYP". ; 这些例程检查特定的"VALTYP"
; [C] IS NOT PRESERVED. ; [C]不被保留
;
FRMNUM: JSR	FRMEVL          ; 计算公式表达式
CHKNUM: CLC                     ; 清除进位标志
	SKIP1                   ; 跳过下一条指令
CHKSTR: SEC			;SET CARRY. ; 设置进位标志
CHKVAL: BIT	VALTYP		;WILL NOT F UP "VALTYP". ; 不会破坏"VALTYP"
	BMI	DOCSTR          ; 如果为负(字符串)，跳转到DOCSTR
	BCS	CHKERR          ; 如果进位设置，跳转到CHKERR
CHKOK:	RTS                     ; 返回
DOCSTR: BCS	CHKOK           ; 如果进位设置，跳转到CHKOK
CHKERR: LDXI	ERRTM           ; 加载"类型不匹配"错误码
ERRGO4: JMP	ERROR           ; 跳转到错误处理
;
; THE FORMULA EVALUATOR STARTS WITH ; 公式求值器开始时
; [TXTPTR] POINTING TO THE FIRST CHARACTER OF THE FORMULA. ; [TXTPTR]指向公式的第一个字符
; AT THE END [TXTPTR] POINTS TO THE TERMINATOR. ; 结束时[TXTPTR]指向终止符
; THE RESULT IS LEFT IN THE FAC. ; 结果留在FAC中
; ON RETURN [A] DOES NOT REFLECT THE TERMINATOR. ; 返回时[A]不反映终止符
;
; THE FORMULA EVALUATOR USES THE OPERATOR LIST (OPTAB) ; 公式求值器使用运算符列表(OPTAB)
; TO DETERMINE PRECEDENCE AND DISPATCH ADDRESSES FOR  ; 来确定每个运算符的优先级和分发地址
; EACH OPERATOR.
; A TEMPORARY RESULT ON THE STACK HAS THE FOLLOWING FORMAT. ; 栈上的临时结果具有以下格式：
;	THE ADDRESS OF THE OPERATOR ROUTINE. ;	运算符例程的地址
;	THE FLOATING POINT TEMPORARY RESULT. ;	浮点临时结果
;	THE PRECEDENCE OF THE OPERATOR. ;	运算符的优先级
;
FRMEVL: LDX	TXTPTR          ; 加载文本指针低字节
	BNE	FRMEV1          ; 如果不为零，跳转到FRMEV1
	DEC	TXTPTR+1        ; 文本指针高字节减1
FRMEV1: DEC	TXTPTR          ; 文本指针低字节减1
	LDXI	0		;INITIAL DUMMY PRECEDENCE IS 0. ; 初始虚拟优先级为0
	SKIP1                   ; 跳过下一条指令
LPOPER: PHA			;SAVE LOW PRECEDENCE. (MASK.) ; 保存低优先级(掩码)
	TXA                     ; 传输X到A
	PHA			;SAVE HIGH PRECEDENCE. ; 保存高优先级
	LDAI	1               ; A寄存器设为1
	JSR	GETSTK		;MAKE SURE THERE IS ROOM FOR ; 确保有空间用于
				;RECURSIVE CALLS. ; 递归调用
	JSR	EVAL		;EVALUATE SOMETHING. ; 求值某些内容
	CLR	OPMASK		;PREPARE TO BUILD MASK MAYBE. ; 准备可能构建掩码
TSTOP:	JSR	CHRGOT		;REGET LAST CHARACTER. ; 重新获取最后一个字符
LOPREL: SEC			;PREP TO SUBTRACT. ; 准备减法
	SBCI	GREATK		;IS CURRENT CHARACTER A RELATION? ; 当前字符是关系运算符吗?
	BCC	ENDREL		;NO. RELATIONS ALL THROUGH. ; 不是，关系运算符处理完毕
	CMPI	LESSTK-GREATK+1 ;REALLY RELATIONAL? ; 确实是关系运算符吗?
	BCS	ENDREL		;NO -- JUST BIG. ; 不是，只是较大
	CMPI	1		;RESET CARRY FOR ZERO ONLY. ; 仅为零重置进位
	ROL	A,		;0 TO 1, 1 TO 2, 2 TO 4. ; 0转1, 1转2, 2转4
	EORI	1               ; 异或1
	EOR	OPMASK		;BRING IN THE OLD BITS. ; 带入旧位
	CMP	OPMASK		;MAKE SURE THE NEW MASK IS BIGGER. ; 确保新掩码更大
	BCC	SNERR5		;SYNTAX ERROR. BECAUSE TWO OF THE SAME. ; 语法错误，因为两个相同
	STA	OPMASK		;SAVE MASK. ; 保存掩码
	JSR	CHRGET          ; 获取下一个字符
	JMP	LOPREL		;GET THE NEXT CANDIDATE. ; 获取下一个候选
ENDREL: LDX	OPMASK		;WERE THERE ANY? ; 有任何关系运算符吗?
	BNE	FINREL		;YES, HANDLE AS SPECIAL OP. ; 有，作为特殊运算符处理
	BCS	QOP		;NOT AN OPERATOR. ; 不是运算符
	ADCI	GREATK-PLUSTK   ; 调整值
	BCC	QOP		;NOT AN OPERATOR. ; 不是运算符
	ADC	VALTYP		;[C]=1. ; [C]=1
	JEQ	CAT		;ONLY IF [A]=0 AND [VALTYP]=-1 (A STR). ; 仅当[A]=0且[VALTYP]=-1(字符串)
	ADCI	^O377		;GET BACK ORIGINAL [A]. ; 恢复原始[A]
	STA	INDEX1          ; 存储到INDEX1
	ASL	A,		;MULTIPLY BY 2. ; 乘以2
	ADC	INDEX1		;BY THREE. ; 乘以3
	TAY			;SET UP FOR LATER. ; 为后续设置
QPREC:	PLA			;GET PREVIOUS PRECEDENCE. ; 获取先前优先级
	CMP	OPTAB,Y		;IS OLD PRECEDENCE GREATER OR EQUAL? ; 旧优先级是否大于或等于?
	BCS	QCHNUM		;YES, GO OPERATE. ; 是，去操作
	JSR	CHKNUM		;CAN'T BE STRING HERE. ; 此处不能是字符串
DOPREC: PHA			;SAVE OLD PRECEDENCE. ; 保存旧优先级
NEGPRC: JSR	DOPRE1		;SET A RETURN ADDRESS FOR OP. ; 为运算符设置返回地址
	PLA			;PULL OFF PREVIOUS PRECEDENCE. ; 取出先前优先级
	LDY	OPPTR		;GET POINTER TO OP. ; 获取指向运算符的指针
	BPL	QPREC1		;THAT'S A REAL OPERATOR. ; 那是真实运算符
	TAX			;DONE ? ; 完成了吗?
	BEQ	QOPGO		;DONE ! ; 完成了!
	BNE	PULSTK          ; 跳转到PULSTK
FINREL: LSR	VALTYP		;GET VALUE TYPE INTO "C". ; 获取值类型到"C"
	TXA                     ; 传输X到A
	ROL	A,		;PUT VALTYP INTO LOW ORDER BIT OF MASK. ; 将VALTYP放入掩码的低位
	LDX	TXTPTR		;DECREMENT TEXT POINTER. ; 递减文本指针
	BNE	FINRE2          ; 如果不为零，跳转到FINRE2
	DEC	TXTPTR+1        ; 文本指针高字节减1
FINRE2: DEC	TXTPTR          ; 文本指针低字节减1
	LDYI	PTDORL-OPTAB	;MAKE [YREG] POINT AT OPERATOR ENTRY. ; 让[YREG]指向运算符条目
	STA	OPMASK		;SAVE THE OPERATION MASK. ; 保存操作掩码
	BNE	QPREC		;SAVE IT ALL. BR ALWAYS. ; 保存全部，总是跳转
				;NOTE B7(VALTYP)=0 SO CHKNUM CALL IS OK. ; 注意B7(VALTYP)=0，因此CHKNUM调用正常
QPREC1: CMP	OPTAB,Y		;LAST PRECEDENCE IS GREATER? ; 最后优先级更大吗?
	BCS	PULSTK		;YES, GO OPERATE. ; 是，去操作
	BCC	DOPREC		;NO SAVE ARGUMENT AND GET OTHER OPERAND. ; 否，保存参数并获取其他操作数
DOPRE1: LDA	OPTAB+2,Y       ; 获取运算符分发地址低字节
	PHA			;DISP ADDR GOES ONTO STACK. ; 分发地址入栈
	LDA	OPTAB+1,Y       ; 获取运算符分发地址高字节
	PHA                     ; 入栈
	JSR	PUSHF1		;SAVE FAC ON STACK UNPACKED. ; 将FAC未打包保存到栈上
	LDA	OPMASK		;[ACCA] MAY BE MASK FOR REL. ; [ACCA]可能是关系运算符掩码
	JMP	LPOPER          ; 跳转到LPOPER
SNERR5: JMP	SNERR		;GO TO AN ERROR. ; 跳转到语法错误
PUSHF1: LDA	FACSGN          ; 加载FAC符号
	LDX	OPTAB,Y,	;GET HIGH PRECEDENCE. ; 获取高优先级
PUSHF:	TAY			;GET POINTER INTO STACK. ; 获取指向堆栈的指针
	PLA                     ; 弹出返回地址低字节
	STA	INDEX1          ; 存储到INDEX1
	INC	INDEX1          ; INDEX1加1
	PLA                     ; 弹出返回地址高字节
	STA	INDEX1+1        ; 存储到INDEX1+1
	TYA                     ; 传输Y到A
				;STORE FAC ON STACK UNPACKED. ; 将FAC未打包存储到栈上
	PHA			;START WITH SIGN SET UP. ; 从设置符号开始
FORPSH: JSR	ROUND		;PUT ROUNDED FAC ON STACK. ; 将舍入后的FAC放入栈中
	LDA	FACLO		;ENTRY POINT TO SKIP STORING SIGN. ; 跳过存储符号的入口点
	PHA                     ; 入栈
	LDA	FACMO           ; 加载FAC中间字节
	PHA                     ; 入栈
IFN	ADDPRC,<                 ; 如果定义了ADDPRC
	LDA	FACMOH          ; 加载FAC中间高字节
	PHA>                    ; 入栈
	LDA	FACHO           ; 加载FAC高字节
	PHA                     ; 入栈
	LDA	FACEXP          ; 加载FAC指数
	PHA                     ; 入栈
	JMPD	INDEX1		;RETURN. ; 跳转到INDEX1指向的地址返回
QOP:	LDYI	255             ; Y寄存器设为255
	PLA			;GET HIGH PRECEDENCE OF LAST OP. ; 获取最后运算符的高优先级
QOPGO:	BEQ	QOPRTS		;DONE ! ; 完成!
QCHNUM: CMPI	100		;RELATIONAL OPERATOR? ; 关系运算符吗?
	BEQ	UNPSTK		;YES, DON'T CHECK OPERAND. ; 是，不检查操作数
	JSR	CHKNUM		;MUST BE NUMBER. ; 必须是数字
UNPSTK: STY	OPPTR		;SAVE OPERATOR'S POINTER FOR NEXT TIME. ; 保存运算符指针供下次使用
PULSTK: PLA			;GET MASK FOR REL OP IF IT IS ONE. ; 获取关系运算符掩码(如果是)
	LSR	A,		;SETUP [C] FOR DOREL'S "CHKVAL". ; 为DOREL的"CHKVAL"设置[C]
	STA	DOMASK		;SAVE FOR "DOCMP". ; 保存供"DOCMP"使用
	PLA			;UNPACK STACK INTO ARG. ; 从栈中解包到ARG
	STA	ARGEXP          ; 存储到ARG指数
	PLA                     ; 弹出
	STA	ARGHO           ; 存储到ARG高字节
IFN	ADDPRC,<                 ; 如果定义了ADDPRC
	PLA                     ; 弹出
	STA	ARGMOH>         ; 存储到ARG中间高字节
	PLA                     ; 弹出
	STA	ARGMO           ; 存储到ARG中间字节
	PLA                     ; 弹出
	STA	ARGLO           ; 存储到ARG低字节
	PLA                     ; 弹出
	STA	ARGSGN          ; 存储到ARG符号
	EOR	FACSGN		;GET PROBABLE RESULT SIGN. ; 获取可能的结果符号
	STA	ARISGN		;ARITHMETIC SIGN. USED BY ; 算术符号，用于
				;ADD, SUB, MULT, DIV. ; 加、减、乘、除
QOPRTS: LDA	FACEXP		;GET IT AND SET CODES. ; 获取并设置代码
UNPRTS: RTS			;RETURN. ; 返回

EVAL:	CLR	VALTYP		;ASSUME VALUE WILL BE NUMERIC. ; 假设值为数字
EVAL0:	JSR	CHRGET		;GET A CHARACTER. ; 获取一个字符
	BCS	EVAL2           ; 如果为数字/字母，跳转到EVAL2
EVAL1:	JMP	FIN		;IT IS A NUMBER. ; 是数字，跳转到FIN
EVAL2:	JSR	ISLETC		;VARIABLE NAME? ; 是变量名吗?
	BCS	ISVAR		;YES. ; 是，跳转到ISVAR
IFE	REALIO-3,<             ; 如果REALIO=3
	CMPI	PI              ; 比较是否为PI常量
	BNE	QDOT            ; 如果不是，跳转到QDOT
	LDWDI	PIVAL           ; 加载PI值地址
	JSR	MOVFM		;PUT VALUE IN FOR PI. ; 将PI值移动到FAC
	JMP	CHRGET          ; 跳转到CHRGET
PIVAL:	^O202                ; PI的指数
	^O111                ; PI的高字节
	^O017                ; PI的中间字节
	^O332                ; PI的中间低字节
	^O241>               ; PI的低字节
QDOT:	CMPI	"."		;LEADING CHARACTER OF CONSTANT? ; 常量的前导字符?
	BEQ	EVAL1           ; 是，跳转到EVAL1
	CMPI	MINUTK		;NEGATION? ; 负号?
	BEQ	DOMIN		;SHO IS. ; 是，跳转到DOMIN
	CMPI	PLUSTK          ; 正号?
	BEQ	EVAL0           ; 是，跳转到EVAL0
	CMPI	34		;A QUOTE? A STRING? ; 引号?字符串?
	BNE	EVAL3           ; 不是，跳转到EVAL3
STRTXT: LDWD	TXTPTR          ; 加载文本指针
	ADCI	0		;TO INC, ADD C=1. ; 为了增加，加C=1
	BCC	STRTX2          ; 如果无进位，跳转到STRTX2
	INY                     ; Y寄存器加1
STRTX2: JSR	STRLIT		;YES. GO PROCESS IT. ; 是，处理字符串字面量
	JMP	ST2TXT          ; 跳转到ST2TXT
EVAL3:	CMPI	NOTTK		;CHECK FOR "NOT" OPERATOR. ; 检查"NOT"运算符
	BNE	EVAL4           ; 不是，跳转到EVAL4
	LDYI	NOTTAB-OPTAB		;"NOT" HAS PRECEDENCE 90. ; "NOT"优先级为90
	BNE	GONPRC		;GO DO ITS EVALUATION. ; 跳转到GONPRC执行求值
NOTOP:	JSR	AYINT		;INTEGERIZE. ; 转换为整数
	LDA	FACLO		;GET THE ARGUMENT. ; 获取参数
	EORI	255             ; 按位取反
	TAY                     ; 传输到Y
	LDA	FACMO           ; 加载FAC中间字节
	EORI	255             ; 按位取反
	JMP	GIVAYF		;FLOAT [Y,A] AS RESULT IN FAC. ; 将[Y,A]浮点化作为FAC结果
				;AND RETURN. ; 并返回
EVAL4:	CMPI	FNTK		;USER-DEFINED FUNCTION? ; 用户定义函数?
	JEQ	FNDOER          ; 是，跳转到FNDOER
	CMPI	ONEFUN		;A FUNCTION NAME? ; 函数名?
	BCC	PARCHK		;FUNCTIONS ARE THE HIGHEST NUMBERED ; 函数是编号最高的
	JMP	ISFUN		;CHARACTERS SO NO NEED TO CHECK ; 字符，因此无需检查
				;AN UPPER-BOUND. ; 上限
PARCHK: JSR	CHKOPN		;ONLY POSSIBILITY LEFT IS ; 剩下的唯一可能是
	JSR	FRMEVL		;A FORMULA IN PARENTHESIS. ; 括号中的公式
				;RECURSIVELY EVALUATE THE FORMULA. ; 递归求值公式
CHKCLS: LDAI	41		;CHECK FOR A RIGHT PARENTHESE ; 检查右括号
	SKIP2                   ; 跳过下一条指令
CHKOPN: LDAI	40              ; 检查左括号
	SKIP2                   ; 跳过下一条指令
CHKCOM: LDAI	44              ; 检查逗号
;
; "SYNCHK" LOOKS AT THE CURRENT CHARACTER TO MAKE SURE IT ; "SYNCHK"查看当前字符以确保它是
; IS THE SPECIFIC THING LOADED INTO ACCA JUST BEFORE THE CALL TO ; 在调用"SYNCHK"之前加载到ACCA的特定内容
; "SYNCHK". IF NOT, IT CALLS THE "SYNTAX ERROR" ROUTINE. ; 如果不是，则调用"语法错误"例程
; OTHERWISE IT GOBBLES THE NEXT CHAR AND RETURNS, ; 否则它消耗下一个字符并返回
;
; [A]=NEW CHAR AND TXTPTR IS ADVANCED BY "CHRGET". ; [A]=新字符，TXTPTR通过"CHRGET"前进
;
SYNCHR: LDYI	0               ; Y寄存器清零
	CMPDY	TXTPTR		;CHARACTERS EQUAL? ; 字符相等吗?
	BNE	SNERR           ; 不相等，跳转到语法错误
CHRGO5: JMP	CHRGET          ; 跳转到CHRGET
SNERR:	LDXI	ERRSN		;"SYNTAX ERROR" ; "语法错误"
	JMP	ERROR           ; 跳转到错误处理
DOMIN:	LDYI	NEGTAB-OPTAB	;A PRECEDENCE BELOW "^". ; 优先级低于"^"
GONPRC: PLA			;GET RID OF RTS ADDR. ; 丢弃返回地址
	PLA                     ; 弹出
	JMP	NEGPRC		;EVALUTE FOR NEGATION. ; 为求负进行求值

ISVAR:	JSR	PTRGET		;GET A PNTR TO VARIABLE. ; 获取指向变量的指针
ISVRET: STWD	FACMO          ; 存储到FAC中间字节和低字节
IFN	TIME!EXTIO,<          ; 如果定义了TIME或EXTIO
	LDWD	VARNAM>		;CHECK TIME,TIME$,STATUS. ; 检查TIME,TIME$,STATUS
	LDX	VALTYP          ; 加载值类型
	BEQ	GOOO		;THE STRING IS SET UP. ; 字符串已设置
	LDXI	0               ; X寄存器清零
	STX	FACOV           ; 存储到FAC溢出位
IFN	TIME,<                 ; 如果定义了TIME
	BIT	FACLO		;AN ARRAY? ; 是数组吗?
	BPL	STRRTS		;YES. ; 是，跳转到STRRTS
	CMPI	"T"		;TI$? ; 是TI$吗?
	BNE	STRRTS          ; 不是，跳转到STRRTS
	CPYI	"I"+128         ; 比较第二个字符
	BNE	STRRTS          ; 不匹配，跳转到STRRTS
	JSR	GETTIM		;YES. PUT TIME IN FACMOH-LO. ; 是，将时间放入FACMOH-LO
	STY	TENEXP		;Y=0. ; Y=0
	DEY                     ; Y减1
	STY	FBUFPT          ; 存储到FBUFPT
	LDYI	6		;SIX	DIGITS TO PRINT. ; 要打印的6位数字
	STY	DECCNT          ; 存储到DECCNT
	LDYI	FDCEND-FOUTBL   ; 设置FOUT表偏移
	JSR	FOUTIM		;CONVERT TO ASCII. ; 转换为ASCII
	JMP	TIMSTR>         ; 跳转到TIMSTR
STRRTS: RTS                     ; 返回
GOOO:
IFN	INTPRC,<                 ; 如果定义了INTPRC
	LDX	INTFLG          ; 加载整数标志
	BPL	GOOOOO          ; 如果为正(浮点)，跳转到GOOOOO
	LDYI	0               ; Y寄存器清零
	LDADY	FACMO		;FETCH HIGH. ; 获取高字节
	TAX                     ; 传输到X
	INY                     ; Y加1
	LDADY	FACMO           ; 获取低字节
	TAY			;PUT LOW IN Y. ; 低字节放入Y
	TXA			;GET HIGH IN A. ; 高字节放入A
	JMP	GIVAYF>		;FLOAT AND RETURN. ; 浮点化并返回
GOOOOO:
IFN	TIME,<                 ; 如果定义了TIME
	BIT	FACLO		;AN ARRAY? ; 是数组吗?
	BPL	GOMOVF		;YES. ; 是，跳转到GOMOVF
	CMPI	"T"              ; 比较是否为"T"
	BNE	QSTATV          ; 不是，跳转到QSTATV
	CPYI	"I"              ; 比较是否为"I"
	BNE	GOMOVF          ; 不是，跳转到GOMOVF
	JSR	GETTIM           ; 获取时间
	TYA			;FOR FLOATB. ; 为FLOATB准备
	LDXI	160		;SET EXPONNENT. ; 设置指数
	JMP	FLOATB          ; 跳转到FLOATB
GETTIM: LDWDI	<CQTIMR-2>      ; 加载计时器地址
	SEI			;TURN OF INT SYS. ; 关闭中断系统
	JSR	MOVFM           ; 移动到FAC
	CLI			;BACK ON. ; 重新开启中断
	STY	FACHO		;ZERO HIGHEST. ; 清零最高字节
	RTS>                    ; 返回
QSTATV:
IFN	EXTIO,<                 ; 如果定义了EXTIO
	CMPI	"S"              ; 比较是否为"S"
	BNE	GOMOVF          ; 不是，跳转到GOMOVF
	CPYI	"T"              ; 比较是否为"T"
	BNE	GOMOVF          ; 不是，跳转到GOMOVF
	LDA	CQSTAT          ; 加载状态
	JMP	FLOAT>          ; 浮点化并返回
GOMOVF:>
IFN	TIME!EXTIO,<          ; 如果定义了TIME或EXTIO
	LDWD	FACMO>          ; 加载FAC中间和低字节
	JMP	MOVFM		;MOVE ACTUAL VALUE IN. ; 移动实际值到FAC
				;AND RETURN. ; 并返回

ISFUN:	ASL	A,		;MULTIPLY BY TWO. ; 乘以2
	PHA                     ; 入栈
	TAX                     ; 传输到X
	JSR	CHRGET		;SET UP FOR SYNCHK. ; 为SYNCHK设置
	CPXI	2*LASNUM-256+1	;IS IT PAST "LASNUM"? ; 超过"LASNUM"了吗?
	BCC	OKNORM		;NO, MUST BE NORMAL FUNCTION. ; 没有，必须是普通函数
;
; MOST FUNCTIONS TAKE A SINGLE ARGUMENT. ; 大多数函数接受单个参数
; THE RETURN ADDRESS OF THESE FUNCTIONS IS "CHKNUM" ; 这些函数的返回地址是"CHKNUM"
; WHICH ASCERTAINS THAT [VALTYP]=0  (NUMERIC). ; 它确认[VALTYP]=0(数字)
; NORMAL FUNCTIONS THAT RETURN STRING RESULTS ; 返回字符串结果的普通函数
; (E.G., CHR$) MUST POP OFF THAT RETURN ADDR AND ; (例如CHR$)必须弹出该返回地址并
; RETURN DIRECTLY TO "FRMEVL". ; 直接返回到"FRMEVL"
;
; THE SO-CALLED "FUNNY" FUNCTIONS CAN TAKE MORE THAN ONE ARGUMENT, ; 所谓的"特殊"函数可以接受多个参数
; THE FIRST OF WHICH MUST BE STRING AND THE SECOND OF WHICH ; 第一个必须是字符串，第二个必须是
; MUST BE A NUMBER BETWEEN 0 AND 255. ; 0到255之间的数字
; THE CLOSED PARENTHESIS MUST BE CHECKED AND RETURN IS DIRECTLY ; 必须检查右括号，并且直接返回到
; TO "FRMEVL" WITH THE TEXT PNTR POINTING BEYOND THE ")". ; "FRMEVL"，文本指针指向")"之后
; THE POINTER TO THE DESCRIPTOR OF THE STRING ARGUMENT ; 指向字符串参数描述符的指针
; IS STORED ON THE STACK UNDERNEATH THE VALUE OF THE ; 存储在整数参数值的下方的栈中
; INTEGER ARGUMENT.
;
	JSR	CHKOPN		;CHECK FOR AN OPEN PARENTHESE ; 检查左括号
	JSR	FRMEVL		;EAT OPEN PAREN AND FIRST ARG. ; 消耗左括号和第一个参数
	JSR	CHKCOM		;TWO ARGS SO COMMA MUST DELIMIT. ; 两个参数，必须用逗号分隔
	JSR	CHKSTR		;MAKE SURE FIRST WAS STRING. ; 确保第一个是字符串
	PLA			;GET FUNCTION NUMBER. ; 获取函数编号
	TAX                     ; 传输到X
	PSHWD	FACMO		;SAVE POINTER AT STRING DESCRIPTOR ; 保存字符串描述符指针
	TXA                     ; 传输X到A
	PHA			;RESAVE FUNCTION NUMBER. ; 重新保存函数编号
				;THIS MUST BE ON STACK SINCE RECURSIVE. ; 由于递归，必须在栈上
	JSR	GETBYT		;[X]=VALUE OF FORMULA. ; [X]=公式值
	PLA			;GET FUNCTION NUMBER. ; 获取函数编号
	TAY                     ; 传输到Y
	TXA                     ; 传输X到A
	PHA                     ; 入栈
	JMP	FINGO		;DISPATCH TO FUNCTION. ; 分发到函数
OKNORM: JSR	PARCHK		;READ A FORMULA SURROUNDED BY PARENS. ; 读取括号包围的公式
	PLA			;GET DISPATCH FUNCTION. ; 获取分发函数
	TAY                     ; 传输到Y
FINGO:	LDA	FUNDSP-2*ONEFUN+256,Y,	;MODIFY DISPATCH ADDRESS. ; 修改分发地址
	STA	JMPER+1         ; 存储到JMPER+1
	LDA	FUNDSP-2*ONEFUN+257,Y ; 获取分发地址高字节
	STA	JMPER+2         ; 存储到JMPER+2
	JSR	JMPER		;DISPATCH! ; 分发!
				;STRING FUNCTIONS REMOVE THIS RET ADDR. ; 字符串函数移除此返回地址
	JMP	CHKNUM		;CHECK IT FOR NUMERICNESS AND RETURN. ; 检查是否为数字并返回

OROP:	LDYI	255		;MUST ALWAYS COMPLEMENT.. ; 必须总是取补
	SKIP2                   ; 跳过下一条指令
ANDOP:	LDYI	0               ; Y寄存器清零
	STY	COUNT		;OPERATOR. ; 运算符
	JSR	AYINT		;[FACMO&LO]=INT VALUE AND CHECK SIZE. ; [FACMO&LO]=整数值并检查大小
	LDA	FACMO		;USE DEMORGAN'S LAW ON HIGH ; 对高字节使用德摩根定律
	EOR	COUNT           ; 异或COUNT
	STA	INTEGR          ; 存储到INTEGR
	LDA	FACLO		;AND LOW. ; 对低字节
	EOR	COUNT           ; 异或COUNT
	STA	INTEGR+1        ; 存储到INTEGR+1
	JSR	MOVFA           ; 移动ARG到FAC
	JSR	AYINT		;[FACMO&LO]=INT OF ARG. ; [FACMO&LO]=ARG的整数
	LDA	FACLO           ; 加载FAC低字节
	EOR	COUNT           ; 异或COUNT
	AND	INTEGR+1        ; 与INTEGR+1与
	EOR	COUNT		;FINISH OUT DEMORGAN. ; 完成德摩根定律
	TAY			;SAVE HIGH. ; 保存高字节
	LDA	FACMO           ; 加载FAC中间字节
	EOR	COUNT           ; 异或COUNT
	AND	INTEGR          ; 与INTEGR与
	EOR	COUNT           ; 异或COUNT
	JMP	GIVAYF		;FLOAT [A.Y] AND RET TO USER. ; 浮点化[A.Y]并返回用户

;
; TIME TO PERFORM A RELATIONAL OPERATOR. ; 执行关系运算符的时候
; [DOMASK] CONTAINS THE BITS AS TO WHICH RELATIONAL ; [DOMASK]包含指示是哪个关系运算符的位
; OPERATOR IT WAS. CARRY BIT ON=STRING COMPARE. ; 进位位开启=字符串比较
;
DOREL:	JSR	CHKVAL		;CHECK FOR MATCH. ; 检查匹配
	BCS	STRCMP		;IT IS A STRING. ; 是字符串，跳转到STRCMP
	LDA	ARGSGN		;PACK ARG FOR FCOMP. ; 为FCOMP打包ARG
	ORAI	127             ; 或127
	AND	ARGHO           ; 与ARG高字节与
	STA	ARGHO           ; 存储到ARG高字节
	LDWDI	ARGEXP          ; 加载ARG指数
	JSR	FCOMP           ; 浮点比较
	TAX                     ; 传输结果到X
	JMP	QCOMP           ; 跳转到QCOMP
STRCMP: CLR	VALTYP		;RESULT WILL BE NUMERIC. ; 结果将是数字
	DEC	OPMASK		;TURN OFF VALTYP WHICH WAS STRING. ; 关闭原是字符串的VALTYP
	JSR	FREFAC		;FREE THE FACLO STRING. ; 释放FACLO字符串
	STA	DSCTMP		;SAVE FOR LATER. ; 保存供后续使用
	STXY	DSCTMP+1        ; 存储X和Y到DSCTMP+1
	LDWD	ARGMO		;GET POINTER TO OTHER STRING. ; 获取指向另一个字符串的指针
	JSR	FRETMP		;FREES FIRST DESC POINTER. ; 释放第一个描述符指针
	STXY	ARGMO           ; 存储X和Y到ARGMO
	TAX			;COPY COUNT INTO X. ; 复制计数到X
	SEC                     ; 设置进位标志
	SBC	DSCTMP		;WHICH IS GREATER. IF 0, ALL SET UP. ; 哪个更大。如果为0，全部设置完毕
	BEQ	STASGN		;JUST PUT SIGN OF DIFFERENCE AWAY. ; 只需存储差异的符号
	LDAI	1               ; A寄存器设为1
	BCC	STASGN		;SIGN IS POSITIVE. ; 符号为正
	LDX	DSCTMP		;LENGTH OF FAC IS SHORTER. ; FAC长度较短
	LDAI	^O377		;GET A MINUS 1 FOR NEGATIVES. ; 获取负数的-1
STASGN: STA	FACSGN		;KEEP FOR LATER. ; 保存供后续使用
	LDYI	255		;SET POINTER TO FIRST STRING. (ARG.) ; 设置指向第一个字符串的指针(ARG)
	INX			;TO LOOP PROPERLY. ; 为了正确循环
NXTCMP: INY                     ; Y加1
	DEX			;ANY CHARACTERS LEFT TO COMPARE? ; 还有字符要比较吗?
	BNE	GETCMP		;NOT DONE YET. ; 尚未完成
	LDX	FACSGN		;USE SIGN OF LENGTH DIFFERENCE ; 使用长度差异的符号
				;SINCE ALL CHARACTERS ARE THE SAME. ; 因为所有字符都相同
QCOMP:	BMI	DOCMP		;C IS ALWAYS SET THEN. ; 那么C总是设置
	CLC                     ; 清除进位标志
	BCC	DOCMP		;ALWAYS BRANCH. ; 总是跳转
GETCMP: LDADY	ARGMO		;GET NEXT CHAR TO COMPARE. ; 获取下一个要比较的字符
	CMPDY	DSCTMP+1	;SAME? ; 相同吗?
	BEQ	NXTCMP		;YEP. TRY FURTHER. ; 是，继续尝试
	LDXI	^O377		;SET A POSITIVE DIFFERENCE. ; 设置正差异
	BCS	DOCMP		;PUT STACK BACK TOGETHER. ; 重组堆栈
	LDXI	1		;SET A NEGATIVE DIFFERENCE. ; 设置负差异
DOCMP:	INX			;-1 TO 1, 0 TO 2, 1 TO 4. ; -1转1, 0转2, 1转4
	TXA                     ; 传输X到A
	ROL	A,		;SET UP BITS. ; 设置位
	AND	DOMASK          ; 与DOMASK与
	BEQ	GOFLOT          ; 如果为零，跳转到GOFLOT
	LDAI	^O377		;MAP 0 TO 0. ALL OTHERS TO -1. ; 映射0到0，所有其他到-1
GOFLOT: JMP	FLOAT		;FLOAT THE ONE-BYTE RESULT INTO FAC. ; 将一字节结果浮点化到FAC

PAGE                        ; 分页
SUBTTL	DIMENSION AND VARIABLE SEARCHING. ; 子标题：维度和变量搜索
;
; THE "DIM" CODE SETS [DIMFLG] AND THEN FALLS INTO THE VARIABLE SEARCH ; "DIM"代码设置[DIMFLG]，然后进入变量搜索
; ROUTINE, WHICH LOOKS AT DIMFLG AT THREE DIFFERENT POINTS. ; 例程，该例程在三个不同点查看DIMFLG：
;	1) IF AN ENTRY IS FOUND, "DIMFLG" BEING ON INDICATES ; 如果找到条目，"DIMFLG"开启表示
;		A "DOUBLY" DIMENSIONED VARIABLE. ; 一个"双重"维度的变量
;	2) WHEN A NEW ENTRY IS BEING BUILT "DIMFLG" BEING ON ; 当构建新条目时，"DIMFLG"开启表示
;		INDICTAES THE INDICES SHOULD BE USED FOR THE ; 索引应用于每个索引的大小
;		SIZE OF EACH INDEX. OTHERWISE THE DEFAULT OF TEN ; 否则使用默认值10
;		IS USED.
;	3) WHEN THE BUILD ENTRY CODE FINISHES, ONLY IF "DIMFLG" IS OFF ; 当构建条目代码完成时，只有"DIMFLG"关闭
;		WILL INDEXING BE DONE. ; 才会进行索引
;
DIM3:	JSR	CHKCOM		;MUST BE A COMMA ; 必须是逗号
DIM:	TAX			;SET [ACCX] NONZERO. ; 设置[ACCX]非零
				;[ACCA] MUST BE NONZERO TO WORK RIGHT. ; [ACCA]必须非零才能正常工作
DIM1:	JSR	PTRGT1          ; 跳转到PTRGT1
DIMCON: JSR	CHRGOT		;GET LAST CHARACTER. ; 获取最后一个字符
	BNE	DIM3            ; 如果不为零(逗号)，跳转到DIM3
	RTS                     ; 返回
;
; ROUTINE TO READ THE VARIABLE NAME AT THE CURRENT TEXT POSITION ; 例程读取当前文本位置的变量名
; AND  PUT A POINTER TO ITS VALUE IN VARPNT. [TXTPTR] ; 并将指向其值的指针放入VARPNT。[TXTPTR]
; POINTS TO THE TERMINATING CHARCTER.. NOT THAT EVALUATING SUBSCRIPTS ; 指向终止字符。注意在变量名中求值下标
; IN A VARIABLE NAME CAN CAUSE RECURSIVE CALLS TO "PTRGET" SO AT ; 可能导致对"PTRGET"的递归调用，因此在
; THAT POINT ALL VALUES MUST BE STORED ON THE STACK. ; 该点所有值必须存储在栈上
;
PTRGET: LDXI	0		;MAKE [ACCX]=0. ; 设置[ACCX]=0
	JSR	CHRGOT		;RETRIEVE LAST CHARACTER. ; 检索最后一个字符
PTRGT1: STX	DIMFLG		;STORE FLAG AWAY. ; 存储标志
PTRGT2: STA	VARNAM          ; 存储到变量名
	JSR	CHRGOT		;GET CURRENT CHARACTER ; 获取当前字符
				;MAYBE WITH FUNCTION BIT OFF. ; 可能函数位关闭
	JSR	ISLETC		;CHECK FOR LETTER. ; 检查字母
	BCS	PTRGT3		;MUST HAVE A LETTER. ; 必须有字母
INTERR: JMP	SNERR           ; 跳转到语法错误
PTRGT3: LDXI	0		;ASSUME NO SECOND CHARACTER. ; 假设没有第二个字符
	STX	VALTYP		;DEFAULT IS NUMERIC. ; 默认为数字
IFN	INTPRC,<                 ; 如果定义了INTPRC
	STX	INTFLG>		;ASSUME FLOATING. ; 假设浮点
	JSR	CHRGET		;GET FOLLOWING CHARACTER. ; 获取后续字符
	BCC	ISSEC		;CARRY RESET BY CHRGET IF NUMERIC. ; 如果为数字，CHRGET清除进位
	JSR	ISLETC		;SET CARRY IF NOT ALPHABETIC. ; 如果不是字母，设置进位
	BCC	NOSEC		;ALLOW ALPHABETICS. ; 允许字母
ISSEC:	TAX			;IT IS A NUMBER -- SAVE IN ACCX. ; 是数字，保存到ACCX
EATEM:	JSR	CHRGET		;LOOK AT NEXT CHARACTER. ; 查看下一个字符
	BCC	EATEM		;SKIP NUMERICS. ; 跳过数字
	JSR	ISLETC          ; 检查字母
	BCS	EATEM		;SKIP ALPHABETICS. ; 跳过字母
NOSEC:	CMPI	"$"		;IS IT A STRING? ; 是字符串吗?
	BNE	NOTSTR		;IF NOT, [VALTYP]=0. ; 如果不是，[VALTYP]=0
	LDAI	^O377		;SET [VALTYP]=255 (STRING !). ; 设置[VALTYP]=255(字符串!)
	STA	VALTYP          ; 存储到VALTYP
IFN	INTPRC,<                 ; 如果定义了INTPRC
	BNEA	TURNON		;ALWAYS GOES. ; 总是跳转
NOTSTR: CMPI	"%"		;INTEGER VARIABLE? ; 整数变量吗?
	BNE	STRNAM		;NO. ; 不是
	LDA	SUBFLG          ; 加载下标标志
	BNE	INTERR          ; 如果不为零，跳转到语法错误
	LDAI	128             ; A寄存器设为128
	STA	INTFLG		;SET FLAG. ; 设置标志
	ORA	VARNAM		;TURN ON BOTH HIGH BITS. ; 开启两个高位
	STA	VARNAM>         ; 存储到变量名
TURNON: TXA                     ; 传输X到A
	ORAI	128		;TURN ON MSB OF SECOND CHARACTER. ; 开启第二个字符的最高位
	TAX                     ; 传输到X
	JSR	CHRGET		;GET CHARACTER AFTER $. ; 获取$后的字符
IFE	INTPRC,<                 ; 如果没有定义INTPRC
NOTSTR:>
STRNAM: STX	VARNAM+1	;STORE AWAY SECOND CHARACTER. ; 存储第二个字符
	SEC                     ; 设置进位标志
	ORA	SUBFLG		;ADD FLAG WHETHER TO ALLOW ARRAYS. ; 添加是否允许数组的标志
	SBCI	40		;(CHECK FOR "(") WON'T MATCH IF SUBFLG SET. ; (检查"(")如果SUBFLG设置则不匹配
	JEQ	ISARY		;IT IS! ; 是数组，跳转到ISARY
	CLR	SUBFLG		;ALLOW SUBSCRIPTS AGAIN. ; 再次允许下标
	LDA	VARTAB		;PLACE TO START SEARCH. ; 开始搜索的位置
	LDX	VARTAB+1        ; 加载变量表高字节
	LDYI	0               ; Y寄存器清零
STXFND: STX	LOWTR+1         ; 存储到LOWTR+1
LOPFND: STA	LOWTR           ; 存储到LOWTR
	CPX	ARYTAB+1	;AT END OF TABLE YET? ; 到表末尾了吗?
	BNE	LOPFN           ; 不相等，跳转到LOPFN
	CMP	ARYTAB          ; 比较低字节
	BEQ	NOTFNS		;YES. WE COULDN'T FIND IT. ; 是，找不到
LOPFN:	LDA	VARNAM          ; 加载变量名
	CMPDY	LOWTR		;COMPARE HIGH ORDERS. ; 比较高位
	BNE	NOTIT		;NO COMPARISON. ; 不匹配
	LDA	VARNAM+1        ; 加载变量名+1
	INY                     ; Y加1
	CMPDY	LOWTR		;AND THE LOW PART? ; 和低位部分比较?
	BEQ	FINPTR		;THAT'S IT ! THAT'S IT ! ; 匹配，找到!
	DEY                     ; Y减1
NOTIT:	CLC                     ; 清除进位标志
	LDA	LOWTR           ; 加载LOWTR
	ADCI	6+ADDPRC	;MAKES NO DIF AMONG TYPES. ; 类型之间没有区别
	BCC	LOPFND          ; 如果无进位，跳转到LOPFND
	INX                     ; X加1
	BNEA	STXFND		;ALWAYS BRANCHES. ; 总是跳转

;
; TEST FOR A LETTER.	/ CARRY OFF= NOT A LETTER. ; 测试字母	/ 进位关闭=不是字母
;			  CARRY ON= A LETTER. ;			  进位开启=是字母
;
ISLETC: CMPI	"A"              ; 比较是否大于等于"A"
	BCC	ISLRTS		;IF LESS THAN "A", RET. ; 如果小于"A"，返回
	SBCI	"Z"+1           ; 减去"Z"+1
	SEC                     ; 设置进位标志
	SBCI	256-"Z"-1	;RESET CARRY IF [A] .GT. "Z". ; 如果[A]大于"Z"，重置进位
ISLRTS: RTS			;RETURN TO CALLER. ; 返回调用者

NOTFNS: PLA			;CHECK WHO'S CALLING. ; 检查谁在调用
	PHA			;RESTORE IT. ; 恢复它
	CMPI	ISVRET-1-<ISVRET-1>/256*256	;IS EVAL CALLING? ; 是EVAL在调用吗?
	BNE	NOTEVL		;NO, CARRY ON. ; 不是，继续
IFN	REALIO-3,<             ; 如果REALIO不等于3
	TSX                     ; 传输堆栈指针到X
	LDA	258,X            ; 检查返回地址高字节
	CMPI	<<ISVRET-1>/256>
	BNE	NOTEVL>         ; 不相等，跳转到NOTEVL
LDZR:	LDWDI	ZERO		;SET UP PNTR TO SIMULATED ZERO. ; 设置指向模拟零的指针
	RTS			;FOR STRINGS OR NUMERIC. ; 用于字符串或数字
				;AND FOR INTEGERS TOO. ; 也用于整数
NOTEVL:
IFN	TIME!EXTIO,<          ; 如果定义了TIME或EXTIO
	LDWD	VARNAM>         ; 加载变量名
IFN	TIME,<                 ; 如果定义了TIME
	CMPI	"T"              ; 比较是否为"T"
	BNE	QSTAVR          ; 不是，跳转到QSTAVR
	CPYI	"I"+128         ; 比较第二个字符
	BEQ	LDZR            ; 相等，跳转到LDZR
	CPYI	"I"              ; 比较是否为"I"
	BNE	QSTAVR>         ; 不相等，跳转到QSTAVR
IFN	EXTIO!TIME,<          ; 如果定义了EXTIO或TIME
GOBADV: JMP	SNERR>          ; 跳转到语法错误
QSTAVR:
IFN	EXTIO,<                 ; 如果定义了EXTIO
	CMPI	"S"              ; 比较是否为"S"
	BNE	VAROK           ; 不是，跳转到VAROK
	CPYI	"T"              ; 比较是否为"T"
	BEQ	GOBADV>         ; 相等，跳转到GOBADV
VAROK:	LDWD	ARYTAB          ; 加载数组表地址
	STWD	LOWTR		;LOWEST THING TO MOVE. ; 要移动的最低内容
	LDWD	STREND		;GET HIGHEST ADDR TO MOVE. ; 获取要移动的最高地址
	STWD	HIGHTR          ; 存储到HIGHTR
	CLC                     ; 清除进位标志
	ADCI	6+ADDPRC        ; 加6+ADDPRC
	BCC	NOTEVE          ; 如果无进位，跳转到NOTEVE
	INY                     ; Y加1
NOTEVE: STWD	HIGHDS		;PLACE TO STUFF IT. ; 存放位置
	JSR	BLTU		;MOVE IT ALL. ; 移动全部
				;NOTE [Y,A] HAS [HIGHDS] FOR REASON. ; 注意[Y,A]有[HIGHDS]
	LDWD	HIGHDS		;AND SET UP ; 设置
	INY                     ; Y加1
	STWD	ARYTAB		;NEW START OF ARRAY TABLE. ; 数组表的新起始位置
	LDYI	0		;GET ADDR OF VARIABLE ENTRY. ; 获取变量条目的地址
	LDA	VARNAM          ; 加载变量名
	STADY	LOWTR           ; 存储到LOWTR,Y
	INY                     ; Y加1
	LDA	VARNAM+1        ; 加载变量名+1
	STADY	LOWTR		;STORE NAME OF VARIABLE. ; 存储变量名
	LDAI	0               ; A寄存器清零
	INY                     ; Y加1
	STADY	LOWTR           ; 存储到LOWTR,Y
	INY                     ; Y加1
	STADY	LOWTR           ; 存储到LOWTR,Y
	INY                     ; Y加1
	STADY	LOWTR           ; 存储到LOWTR,Y
	INY                     ; Y加1
	STADY	LOWTR		;FOURTH ZERO FOR DEF FUNC. ; DEF FN的第四个零
IFN	ADDPRC,<                 ; 如果定义了ADDPRC
	INY                     ; Y加1
	STADY	LOWTR>          ; 存储到LOWTR,Y
FINPTR: LDA	LOWTR           ; 加载LOWTR
	CLC                     ; 清除进位标志
	ADCI	2               ; 加2
	LDY	LOWTR+1         ; 加载LOWTR+1
	BCC	FINNOW          ; 如果无进位，跳转到FINNOW
	INY                     ; Y加1
FINNOW: STWD	VARPNT		;THIS IS IT ! ; 这就是它!
	RTS                     ; 返回
PAGE                        ; 分页
SUBTTL	MULTIPLE DIMENSION CODE. ; 子标题：多维度代码
FMAPTR: LDA	COUNT           ; 加载计数
	ASL	A,		;MULTIPLY BY 2. ; 乘以2
	ADCI	5		;POINT TO ENTRIES. C CLR'D BY ASL. ; 指向条目，ASL清除进位
	ADC	LOWTR           ; 加LOWTR
	LDY	LOWTR+1         ; 加载LOWTR+1
	BCC	JSRGM           ; 如果无进位，跳转到JSRGM
	INY                     ; Y加1
JSRGM:	STWD	ARYPNT          ; 存储到数组指针
	RTS                     ; 返回

N32768: EXP	144,128,0,0	;-32768. ; -32768的浮点表示

;
; INTIDX READS A FORMULA FROM THE CURRENT POSITION AND ; INTIDX从当前位置读取公式并
; TURNS IT INTO A POSITIVE INTEGER ; 将其转换为正整数
; LEAVING THE RESULT IN FACMO&LO. NEGATIVE ARGUMENTS ; 结果留在FACMO&LO中。不允许
; ARE NOT ALLOWED. ; 负参数
;
INTIDX: JSR	CHRGET          ; 获取字符
	JSR	FRMEVL		;GET A NUMBER ; 获取数字
POSINT: JSR	CHKNUM          ; 检查是否为数字
	LDA	FACSGN          ; 加载FAC符号
	BMI	NONONO		;IF NEGATIVE, BLOW HIM OUT. ; 如果为负，报错
AYINT:	LDA	FACEXP          ; 加载FAC指数
	CMPI	144		;FAC .GT. 32767? ; FAC大于32767?
	BCC	QINTGO          ; 如果小于，跳转到QINTGO
	LDWDI	N32768		;GET ADDR OF -32768. ; 获取-32768的地址
	JSR	FCOMP		;SEE IF FAC=[[Y,A]]. ; 检查FAC是否等于[Y,A]指向的值
NONONO: BNE	FCERR		;NO, FAC IS TOO BIG. ; 不相等，FAC太大
QINTGO: JMP	QINT		;GO TO QINT AND SHOVE IT. ; 跳转到QINT并转换
;
; FORMAT OF ARRAYS IN CORE. ; 内存中数组的格式：
;
; DESCRIPTOR: ; 描述符：
;	LOWBYTE = FIRST CHARACTER. ;	低字节 = 第一个字符
;	HIGHBYTE = SECOND CHARACTER (200 BIT IS STRING FLAG). ;	高字节 = 第二个字符(200位是字符串标志)
; LENGTH OF ARRAY IN CORE IN BYTES (INCLUDES EVERYTHING). ; 内存中数组的长度(字节)(包括所有内容)
; NUMBER OF DIMENSIONS. ; 维度数
; FOR EACH DIMENSION STARTING WITH THE FIRST A LIST ; 对于每个维度，从第一个开始是一个列表
; (2 BYTES EACH) OF THE MAX INDICE+1 ; (每个2字节)的最大索引+1
; THE VALUES ; 值
;
ISARY:	LDA	DIMFLG          ; 加载维度标志
IFN	INTPRC,<                 ; 如果定义了INTPRC
	ORA	INTFLG>         ; 或整数标志
	PHA			;SAVE [DIMFLG] FOR RECURSION. ; 保存[DIMFLG]用于递归
	LDA	VALTYP          ; 加载值类型
	PHA			;SAVE [VALTYP] FOR RECURSION. ; 保存[VALTYP]用于递归
	LDYI	0		;SET NUMBER OF DIMENSIONS TO ZERO. ; 设置维度数为零
INDLOP: TYA			;SAVE NUMBER OF DIMS. ; 保存维度数
	PHA                     ; 入栈
	PSHWD	VARNAM		;SAVE LOOKS. ; 保存外观
	JSR	INTIDX		;EVALUATE INDICE INTO FACMO&LO. ; 将索引求值到FACMO&LO
	PULWD	VARNAM		;GET BACK ALL... WE'RE HOME. ; 恢复所有...我们回来了
	PLA			;(# OF DIMS). ; (维度数)
	TAY                     ; 传输到Y
	TSX                     ; 传输堆栈指针到X
	LDA	258+7
	PHA			;PUSH DIMFLG AND VALTYP FURTHER.
	LDA	257,X
	PHA
	STA	INDICE          ; 存储到索引
	STA	258,X,		;UNDER DIMFLG AND VALTYP.
	STA	INDICE+1        ; 存储到索引+1
    STA	257,X
	INY			;INCREMENT # OF DIMS. ; 增加维度数
	JSR	CHRGOT		;GET TERMINATING CHARACTER. ; 获取终止字符
	CMPI	44		;A COMMA? ; 逗号吗?
	BEQ	INDLOP		;YES. ; 是，继续循环
	STY	COUNT		;SAVE COUNT OF DIMS. ; 保存维度计数
	JSR	CHKCLS		;MUST BE CLOSED PAREN. ; 必须是右括号
	PLA                     ; 弹出
	STA	VALTYP		;GET VALTYP AND ; 获取VALTYP和
	PLA                     ; 弹出
IFN	INTPRC,<                 ; 如果定义了INTPRC
	STA	INTFLG          ; 存储到整数标志
	ANDI	127>            ; 与127与
	STA	DIMFLG		;DIMFLG OFF STACK. ; 从栈中取出DIMFLG
	LDX	ARYTAB		;PLACE TO START SEARCH. ; 开始搜索的位置
	LDA	ARYTAB+1        ; 加载数组表高字节
LOPFDA: STX	LOWTR           ; 存储到LOWTR
	STA	LOWTR+1         ; 存储到LOWTR+1
	CMP	STREND+1	;END OF ARRAYS? ; 数组结束了吗?
	BNE	LOPFDV          ; 不相等，跳转到LOPFDV
	CPX	STREND          ; 比较低字节
	BEQ	NOTFDD		;A FINE THING! NO ARRAY!. ; 太好了!没有数组!
LOPFDV: LDYI	0               ; Y寄存器清零
	LDADY	LOWTR           ; 加载LOWTR,Y
	INY                     ; Y加1
	CMP	VARNAM		;COMPARE HIGH ORDERS. ; 比较高位
	BNE	NMARY1		;NO WAY IS IT THIS. GET OUT OF HERE. ; 不匹配，跳出
	LDA	VARNAM+1        ; 加载变量名+1
	CMPDY	LOWTR		;LOW ORDERS? ; 低位?
	BEQ	GOTARY		;WELL, HERE IT IS !! ; 匹配，找到数组!
NMARY1: INY                     ; Y加1
	LDADY	LOWTR		;GET LENGTH. ; 获取长度
	CLC                     ; 清除进位标志
	ADC	LOWTR           ; 加LOWTR
	TAX                     ; 传输到X
	INY                     ; Y加1
	LDADY	LOWTR           ; 加载LOWTR,Y
	ADC	LOWTR+1         ; 加LOWTR+1
	BCC	LOPFDA		;ALWAYS BRANCHES. ; 总是跳转
BSERR:	LDXI	ERRBS		;GET BAD SUB ERROR NUMBER. ; 获取错误下标错误号
	SKIP2                   ; 跳过下一条指令
FCERR:	LDXI	ERRFC		;TOO BIG. "FUNCTION CALL" ERROR. ; 太大。"函数调用"错误
ERRGO3: JMP	ERROR           ; 跳转到错误处理
GOTARY: LDXI	ERRDD		;PERHAPS A "RE-DIMENSION" ERROR ; 可能是"重新维度"错误
	LDA	DIMFLG		;TEST THE DIMFLG ; 测试维度标志
	BNE	ERRGO3          ; 如果不为零，跳转到错误处理
	JSR	FMAPTR          ; 跳转到FMAPTR
	LDA	COUNT		;GET NUMBER OF DIMS INPUT. ; 获取输入的维度数
	LDYI	4               ; Y寄存器设为4
	CMPDY	LOWTR		;# OF DIMS THE SAME? ; 维度数相同吗?
	BNE	BSERR		;SAME SO GO GET DEFINITION. ; 相同，去获取定义
	JMP	GETDEF          ; 跳转到GETDEF

;
; HERE WHEN VARIABLE IS NOT FOUND IN THE ARRAY TABLE. ; 当在数组表中找不到变量时到这里
;
; BUILDING AN ENTRY. ; 构建一个条目：
;
;	PUT DOWN THE DESCRIPTOR. ;	放置描述符
;	SETUP NUMBER OF DIMENSIONS. ;	设置维度数
;	MAKE SURE THERE IS ROOM FOR THE NEW ENTRY. ;	确保有新条目的空间
;	REMEMBER "VARPNT". ;	记住"VARPNT"
;	TALLY=4.
;	SKIP 2 LOCS FOR LATER FILL IN OF SIZE. ;	跳过2个位置以便稍后填充大小
; LOOP: GET AN INDICE ; 循环：获取一个索引
;	PUT DOWN NUMBER+1 AND INCREMENT VARPTR. ;	放置数字+1并递增VARPTR
;	TALLY=TALLY*NUMBER+1. ;	TALLY=TALLY*数字+1
;	DECREMENT NUMBER-DIMS. ;	递减数字-维度
;	BNE LOOP ;	BNE 循环
;	CALL "REASON" WITH [Y,A] REFLECTING LAST LOC OF VARIABLE. ;	调用"REASON"，[Y,A]反映变量的最后位置
;	UPDATE STREND. ;	更新STREND
;	ZERO ALL. ;	全部清零
;	MAKE TALLY INCLUDE MAXDIMS AND DESCRIPTOR. ;	让TALLY包括最大维度和描述符
;	PUT DOWN TALLY. ;	放置TALLY
;	IF CALLED BY DIMENSION, RETURN. ;	如果由DIMENSION调用，返回
;	OTHERWISE INDEX INTO THE VARIABLE AS IF IT ;	否则索引到变量中，就像在
;	 WERE FOUND ON THE INITIAL SEARCH. ;	 初始搜索中找到它一样
;
NOTFDD: JSR	FMAPTR		;FORM ARYPNT. ; 形成数组指针
	JSR	REASON          ; 跳转到REASON
	LDAI	0               ; A寄存器清零
	TAY                     ; 传输到Y
	STA	CURTOL+1        ; 存储到CURTOL+1
IFE	ADDPRC,<                 ; 如果没有定义ADDPRC
	LDXI	4>              ; X寄存器设为4
IFN	ADDPRC,<                 ; 如果定义了ADDPRC
	LDXI	5>              ; X寄存器设为5
	LDA	VARNAM		;THIS CODE ONLY WORKS FOR INTPRC=1 ; 此代码仅适用于INTPRC=1
	STADY	LOWTR           ; 存储到LOWTR,Y
IFN	ADDPRC,<                 ; 如果定义了ADDPRC
	BPL	NOTFLT          ; 如果为正，跳转到NOTFLT
	DEX>                    ; X减1
NOTFLT: INY                     ; Y加1
	LDA	VARNAM+1        ; 加载变量名+1
	STADY	LOWTR           ; 存储到LOWTR,Y
	BPL	STOMLT          ; 如果为正，跳转到STOMLT
	DEX                     ; X减1
IFN	ADDPRC,<                 ; 如果定义了ADDPRC
	DEX>                    ; X减1
STOMLT: STX	CURTOL          ; 存储到CURTOL
	LDA	COUNT           ; 加载计数
	REPEAT	3,<INY>         ; Y加3
	STADY	LOWTR		;SAVE NUMBER OF DIMENSIONS. ; 保存维度数
LOPPTA: LDXI	11		;DEFAULT SIZE. ; 默认大小
	LDAI	0               ; A寄存器清零
	BIT	DIMFLG          ; 测试维度标志
	BVC	NOTDIM		;NOT IN A DIM STATEMENT. ; 不在DIM语句中
	PLA			;GET LOW ORDER OF INDICE. ; 获取索引低阶
	CLC                     ; 清除进位标志
	ADCI	1               ; 加1
	TAX                     ; 传输到X
	PLA			;GET HIGH PART OF INDICE. ; 获取索引高阶
	ADCI	0               ; 加0
NOTDIM: INY                     ; Y加1
	STADY	LOWTR		;STORE HIGH PART OF INDICE. ; 存储索引高阶
	INY                     ; Y加1
	TXA                     ; 传输X到A
	STADY	LOWTR		;STORE LOW ORDER OF INDICE. ; 存储索引低阶
	JSR	UMULT		;[X,A]=[CURTOL]*[LOWTR,Y] ; [X,A]=[CURTOL]*[LOWTR,Y]
	STX	CURTOL		;SAVE NEW TALLY. ; 保存新计数
	STA	CURTOL+1        ; 存储到CURTOL+1
	LDY	INDEX           ; 加载索引
	DEC	COUNT		;ANY MORE INDICES LEFT? ; 还有索引吗?
	BNE	LOPPTA		;YES. ; 是，继续循环
	ADC	ARYPNT+1        ; 加ARYPNT+1
	BCS	OMERR1		;OVERFLOW. ; 溢出
	STA	ARYPNT+1	;COMPUTE WHERE TO ZERO. ; 计算清零位置
	TAY                     ; 传输到Y
	TXA                     ; 传输X到A
	ADC	ARYPNT          ; 加ARYPNT
	BCC	GREASE          ; 如果无进位，跳转到GREASE
	INY                     ; Y加1
	BEQ	OMERR1          ; 如果为零，跳转到OMERR1
GREASE: JSR	REASON		;GET ROOM. ; 获取空间
	STWD	STREND		;NEW END OF STORAGE. ; 新的存储结束位置
	LDAI	0		;STORING [ACCA] IS FASTER THAN CLEAR. ; 存储[ACCA]比清零快
	INC	CURTOL+1        ; CURTOL+1加1
	LDY	CURTOL          ; 加载CURTOL
	BEQ	DECCUR          ; 如果为零，跳转到DECCUR
ZERITA: DEY                     ; Y减1
	STADY	ARYPNT          ; 存储到ARYPNT,Y
	BNE	ZERITA		;NO. CONTINUE. ; 不为零，继续
DECCUR: DEC	ARYPNT+1        ; ARYPNT+1减1
	DEC	CURTOL+1        ; CURTOL+1减1
	BNE	ZERITA		;DO ANOTHER BLOCK. ; 做另一个块
	INC	ARYPNT+1	;BUMP BACK UP. WILL USE LATER. ; 增加回来，稍后使用
	SEC                     ; 设置进位标志
	LDA	STREND		;RESTORE [ACCA]. ; 恢复[ACCA]
	SBC	LOWTR		;DETERMINE LENGTH. ; 确定长度
	LDYI	2               ; Y寄存器设为2
	STADY	LOWTR		;LOW. ; 低字节
	LDA	STREND+1        ; 加载STREND+1
	INY                     ; Y加1
	SBC	LOWTR+1         ; 减LOWTR+1
	STADY	LOWTR		;HIGH. ; 高字节
	LDA	DIMFLG          ; 加载维度标志
	BNE	DIMRTS		;BYE. ; 不为零，返回
	INY                     ; Y加1
;
; AT THIS POINT [LOWTR,Y] POINTS BEYOND THE SIZE TO THE NUMBER OF 
; DIMENSIONS. STRATEGY: ; 此时 [LOWTR,Y] 指向超出大小的维度数。策略：
;	NUMDIM=NUMBER OF DIMENSIONS. ;	NUMDIM=维度数
;	CURTOL=0.
; INLPNM:GET A NEW INDICE. ;  INLPNM:获取新索引
;	MAKE SURE INDICE IS NOT TOO BIG. ;	确保索引不过大
;	MULTIPLY CURTOL BY CURMAX. ;	CURTOL 乘以 CURMAX
;	ADD INDICE TO CURTOL. ;	将索引加到 CURTOL
;	NUMDIM=NUMDIM-1.
;	BNE	INLPNM.
;	USE [CURTOL]*4 AS OFFSET. ;	使用 [CURTOL]*4 作为偏移量
;
GETDEF: LDADY	LOWTR		;获取维度数
	STA	COUNT		;SAVE A COUNTER. ; 保存计数器
	LDAI	0		;ZERO [CURTOL]. ; 清零 [CURTOL]
	STA	CURTOL		;存储到 CURTOL
INLPNM: STA	CURTOL+1	;存储到 CURTOL+1
	INY			;Y 加 1
	PLA			;GET LOW INDICE. ; 获取索引低字节
	TAX			;传输到 X
	STA	INDICE		;存储到 INDICE
	PLA			;AND THE HIGH PART ; 以及高字节部分
	STA	INDICE+1	;存储到 INDICE+1
	CMPDY	LOWTR		;COMPARE WITH MAX INDICE. ; 与最大索引比较
	BCC	INLPN2		;如果小于，跳转到 INLPN2
	BNE	BSERR7		;IF GREATER, "BAD SUBSCRIPT" ERROR. ; 如果大于，"下标错误"
	INY
	TXA
	CMPDY	LOWTR
	BCC	INLPN1
BSERR7: JMP	BSERR
OMERR1: JMP	OMERR
INLPN2: INY			;Y 加 1
INLPN1: LDA	CURTOL+1	;DON'T MULTIPLY IF CURTOL=0. ; 如果 CURTOL=0 则不乘法
	ORA	CURTOL		;或 CURTOL
	CLC			;PREPARE TO GET INDICE BACK. ; 准备取回索引
	BEQ	ADDIND		;GET HIGH PART OF INDICE BACK. ; 取回索引高字节部分
	JSR	UMULT		;MULTIPLY [CURTOL] BY [LOWTR,Y,Y+1]. ; [CURTOL] 乘以 [LOWTR,Y,Y+1]
	TXA			;传输 X 到 A
	ADC	INDICE		;ADD IN [INDICE]. ; 加上 [INDICE]
	TAX			;传输到 X
	TYA			;传输 Y 到 A
	LDY	INDEX1		;加载 INDEX1
ADDIND: ADC	INDICE+1	;加上 INDICE+1
	STX	CURTOL		;存储到 CURTOL
	DEC	COUNT		;ANY MORE? ; 还有吗？
	BNE	INLPNM		;YES. ; 是，继续循环
	STA	CURTOL+1	;FIX ARRAY BUG **** ; 修复数组错误 ****
IFE	ADDPRC,<		;如果未定义 ADDPRC
	LDXI	4>		;X 设为 4
IFN	ADDPRC,<		;如果定义了 ADDPRC
	LDXI	5		;THIS CODE ONLY WORKS FOR INTPRC=1 ; 此代码仅适用于 INTPRC=1
	LDA	VARNAM		;IF ADDPRC=1. ; 如果 ADDPRC=1
	BPL	NOTFL1		;如果为正，跳转到 NOTFL1
	DEX>			;X 减 1
NOTFL1: LDA	VARNAM+1	;加载变量名+1
	BPL	STOML1		;如果为正，跳转到 STOML1
	DEX			;X 减 1
IFN	ADDPRC,<		;如果定义了 ADDPRC
	DEX>			;X 减 1
STOML1: STX	ADDEND		;存储到 ADDEND
	LDAI	0		;A 清零
	JSR	UMULTD		;ON RTS, A&Y=HI . X=LO. ; 返回时 A&Y=高字节，X=低字节
	TXA			;传输 X 到 A
	ADC	ARYPNT		;加 ARYPNT
	STA	VARPNT		;存储到 VARPNT
	TYA			;传输 Y 到 A
	ADC	ARYPNT+1	;加 ARYPNT+1
	STA	VARPNT+1	;存储到 VARPNT+1
	TAY			;传输到 Y
	LDA	VARPNT		;加载 VARPNT
DIMRTS: RTS			;RETURN TO CALLER. ; 返回调用者
SUBTTL	INTEGER ARITHMETIC ROUTINES. ; 子标题：整数算术例程
	;TWO BYTE UNSIGNED INTEGER MULTIPLY. ; 两字节无符号整数乘法
	;THIS IS FOR MULTIPLY DIMENSIONED ARRAYS. ; 用于多维数组
	; [X,Y]=[X,A]=[CURTOL]*[LOWTR,Y,Y+1]. ; [X,Y]=[X,A]=[CURTOL]*[LOWTR,Y,Y+1]
UMULT:	STY	INDEX		;保存 Y 到 INDEX
	LDADY	LOWTR		;加载 LOWTR,Y
	STA	ADDEND		;LOW, THEN HIGH. ; 低字节，然后高字节
	DEY			;Y 减 1
	LDADY	LOWTR		;PUT [LOWTR,Y,Y+1] IN FASTER MEMORY. ; 将 [LOWTR,Y,Y+1] 放入更快内存
UMULTD: STA	ADDEND+1	;存储到 ADDEND+1
	LDAI	16		;A 设为 16
	STA	DECCNT		;存储到 DECCNT
	LDXI	0		;CLR THE ACCS. ; 清零累加器
	LDYI	0		;RESULT INITIALLY ZERO. ; 结果初始为零
UMULTC: TXA			;传输 X 到 A
	ASL	A,		;MULTIPLY BY TWO. ; 乘以二
	TAX			;传输回 X
	TYA			;传输 Y 到 A
	ROL	A,		;循环左移
	TAY			;传输回 Y
	BCS	OMERR1		;TWO MUCH ! ; 太多！
	ASL	CURTOL		;左移 CURTOL
	ROL	CURTOL+1	;循环左移 CURTOL+1
	BCC	UMLCNT		;NOTHING IN THIS POSITION TO MULTIPLY. ; 此位无数可乘
	CLC			;清进位
	TXA			;传输 X 到 A
	ADC	ADDEND		;加 ADDEND
	TAX			;传输回 X
	TYA			;传输 Y 到 A
	ADC	ADDEND+1	;加 ADDEND+1
	TAY			;传输回 Y
	BCS	OMERR1		;MAN, JUST TOO MUCH ! ; 老兄，还是太多！
UMLCNT: DEC	DECCNT		;DONE? ; 完成？
	BNE	UMULTC		;KEEP IT UP. ; 继续
UMLRTS: RTS			;YES, ALL DONE. ; 是，全部完成
PAGE				;分页
SUBTTL	FRE FUNCTION AND INTEGER TO FLOATING ROUTINES. ; 子标题：FRE 函数和整数转浮点例程
FRE:	LDA	VALTYP		;加载值类型
	BEQ	NOFREF		;如果为数字，跳转到 NOFREF
	JSR	FREFAC		;释放 FAC 指向的字符串
NOFREF: JSR	GARBA2		;执行垃圾收集
	SEC			;置位进位
	LDA	FRETOP		;WE WANT ; 我们要
	SBC	STREND		;[FRETOP]-[STREND]. ; [FRETOP]-[STREND]
	TAY			;传输到 Y
	LDA	FRETOP+1	;加载 FRETOP+1
	SBC	STREND+1	;减去 STREND+1

GIVAYF: LDXI	0		;X 清零
	STX	VALTYP		;强制为数字类型
	STWD	FACHO		;存储到 FACHO
	LDXI	144		;SET EXPONENT TO 2^16. ; 设置指数为 2^16
	JMP	FLOATS		;TURN IT TO A FLOATING PNT #. ; 转为浮点数

POS:	LDY	TRMPOS		;GET POSITION. ; 获取位置
SNGFLT: LDAI	0		;A 清零
	BEQA	GIVAYF		;FLOAT IT. ; 浮点化
PAGE				;分页
SUBTTL	SIMPLE-USER-DEFINED-FUNCTION CODE. ; 子标题：简单用户定义函数代码
;
; NOTE ONLY SINGLE ARGUMENTS ARE ALLOWED TO FUNCTIONS ; 注意函数只允许单参数
; AND FUNCTIONS MUST BE OF THE SINGLE LINE FORM: ; 且函数必须是单行形式：
;	DEF FNA(X)=X^2+X-2
; NO STRINGS CAN BE INVOLVED WITH THESE FUNCTIONS. ; 这些函数不能涉及字符串
;
; IDEA: CREATE A SIMPLE VARIABLE ENTRY ; 想法：创建一个简单变量条目
; WHOSE FIRST CHARACTER HAS THE 200 BIT SET. ; 其首字符设置了 200 位
; THE VALUE WILL BE: ; 其值为：
;
;	A TEXT PNTR TO THE FORMULA. ;	指向公式的文本指针
;	A PNTR TO THE ARGUMENT VARIABLE. ;	指向参数变量的指针
;
; FUNCTION NAMES CAN BE LIKE "FNA4". ; 函数名可以是 "FNA4" 这样的形式
;
;
; SUBROUTINE TO SEE IF WE ARE IN DIRECT MODE. ; 检查是否处于直接模式的子程序
; AND COMPLAIN IF SO. ; 如果是则报错
;
ERRDIR: LDX	CURLIN+1	;DIR MODE HAS [CURLIN]=0,255 ; 直接模式下 [CURLIN]=0,255
	INX			;SO NOW, IS RESULT ZERO? ; 那么现在，结果为零？
	BNE	DIMRTS		;YES. ; 是，返回
	LDXI	ERRID		;INPUT DIRECT ERROR CODE. ; 输入直接错误码
	SKIP2			;跳过下一条指令
ERRGUF: LDXI	ERRUF		;USER DEFINED FUNCTION NEVER DEFINED ; 用户定义函数从未定义
ERRGO1: JMP	ERROR		;跳转到错误处理

DEF:	JSR	GETFNM		;GET A PNTR TO THE FUNCTION. ; 获取指向函数的指针
	JSR	ERRDIR		;检查是否直接模式
	JSR	CHKOPN		;MUST HAVE "(". ; 必须有 "("
	LDAI	128		;A 设为 128
	STA	SUBFLG		;PROHIBIT SUBSCRIPTED VARIABLES. ; 禁止下标变量
	JSR	PTRGET		;GET PNTR TO ARGUMENT. ; 获取指向参数的指针
	JSR	CHKNUM		;IS IT A NUMBER? ; 是数字吗？
	JSR	CHKCLS		;MUST HAVE ")" ; 必须有 ")"
	SYNCHK	EQULTK		;MUST HAVE "=". ; 必须有 "="
IFN	ADDPRC,<PHA>		;PUT CRAZY BYTE ON. ; 放入特殊字节
	PSHWD	VARPNT		;保存变量指针
	PSHWD	TXTPTR		;保存文本指针
	JSR	DATA		;执行 DATA
	JMP	DEFFIN		;跳转到 DEFFIN
;
; SUBROUTINE TO GET A PNTR TO A FUNCTION NAME. ; 获取指向函数名的指针的子程序
;
GETFNM: SYNCHK	FNTK		;MUST START WITH FN. ; 必须以 FN 开头
	ORAI	128		;PUT FUNCTION BIT ON. ; 设置函数位
	STA	SUBFLG		;存储到 SUBFLG
	JSR	PTRGT2		;GET POINTER TO FUNCTION OR CREATE ANEW. ; 获取函数指针或新建
	STWD	DEFPNT		;存储到 DEFPNT
	JMP	CHKNUM		;MAKE SURE IT'S NOT A STRING AND RETURN. ; 确保不是字符串并返回

FNDOER: JSR	GETFNM		;GET THE FUNCTION'S NAME. ; 获取函数名
	PSHWD	DEFPNT		;保存 DEFPNT
	JSR	PARCHK		;EVALUATE PARAMETER. ; 求值参数
	JSR	CHKNUM		;检查是否为数字
	PULWD	DEFPNT		;恢复 DEFPNT
	LDYI	2		;Y 设为 2
	LDADY	DEFPNT		;GET POINTER TO VARIABLE. ; 获取指向变量的指针
	STA	VARPNT		;SAVE VARIABLE POINTER. ; 保存变量指针
	TAX			;传输到 X
	INY			;Y 加 1
	LDADY	DEFPNT		;加载 DEFPNT,Y
	BEQ	ERRGUF		;如果为零，跳转到 ERRGUF
	STA	VARPNT+1	;存储到 VARPNT+1
IFN	ADDPRC,<INY>		;SINCE DEF USES ONLY 4. ; 因为 DEF 只使用 4 字节
DEFSTF: LDADY	VARPNT		;加载 VARPNT,Y
	PHA			;PUSH IT ALL ON STACK. ; 全部压栈
	DEY			;Y 减 1
	BPL	DEFSTF		;如果为正，继续循环
	LDY	VARPNT+1	;加载 VARPNT+1
	JSR	MOVMF		;PUT CURRENT FAC INTO OUR ARG VARIABLE. ; 将当前 FAC 放入我们的参数变量
	PSHWD	TXTPTR		;SAVE TEXT POINTER. ; 保存文本指针
	LDADY	DEFPNT		;PNTR TO FUNCTION. ; 指向函数的指针
	STA	TXTPTR		;存储到 TXTPTR
	INY			;Y 加 1
	LDADY	DEFPNT		;加载 DEFPNT,Y
	STA	TXTPTR+1	;存储到 TXTPTR+1
	PSHWD	VARPNT		;SAVE VARIABLE POINTER. ; 保存变量指针
	JSR	FRMNUM		;EVALUATE FORMULA AND CHECK NUMERIC. ; 求值公式并检查数字
	PULWD	DEFPNT		;恢复 DEFPNT
	JSR	CHRGOT		;获取当前字符
	JNE	SNERR		;IT DIDN'T TERMINATE. HUH? ; 未终止，嗯？
	PULWD	TXTPTR		;RESTORE TEXT PNTR. ; 恢复文本指针
DEFFIN: LDYI	0		;Y 清零
	PLA			;GET OLD ARG VALUE OFF STACK ; 从栈中取出旧参数值
	STADY	DEFPNT		;AND PUT IT BACK IN VARIABLE. ; 放回变量中
	PLA			;弹出
	INY			;Y 加 1
	STADY	DEFPNT		;存储到 DEFPNT,Y
	PLA			;弹出
	INY			;Y 加 1
	STADY	DEFPNT		;存储到 DEFPNT,Y
	PLA			;弹出
	INY			;Y 加 1
	STADY	DEFPNT		;存储到 DEFPNT,Y
IFN	ADDPRC,<		;如果定义了 ADDPRC
	PLA			;弹出
	INY			;Y 加 1
	STADY	DEFPNT>		;存储到 DEFPNT,Y
DEFRTS: RTS			;返回
	PAGE			;分页
SUBTTL	STRING FUNCTIONS. ; 子标题：字符串函数
;
; THE STR$ FUNCTION TAKES A NUMBER AND GIVES A STRING ; STR$ 函数接受数字并返回字符串
; WITH THE CHARACTERS THE OUTPUT OF THE NUMBER ; 字符串包含该数字输出会产生的字符
; WOULD HAVE GIVEN.
;
STR:	JSR	CHKNUM		;ARG HAS TO BE NUMERIC. ; 参数必须是数字
	LDYI	0		;Y 清零
	JSR	FOUTC		;DO ITS OUTPUT. ; 执行输出
	PLA			;弹出
	PLA			;弹出
TIMSTR: LDWDI	LOFBUF		;加载 LOFBUF 地址
	BEQA	STRLIT		;SCAN IT AND TURN IT INTO A STRING. ; 扫描并转为字符串
;
; "STRINI" GET STRING SPACE FOR THE CREATION OF A STRING AND ; "STRINI" 为创建字符串获取字符串空间
; CREATES A DESCRIPTOR FOR IT IN "DSCTMP". ; 并在 "DSCTMP" 中为其创建描述符
;
STRINI: LDXY	FACMO		;GET FACMO TO STORE IN DSCPNT. ; 获取 FACMO 存储到 DSCPNT
	STXY	DSCPNT		;RETAIN THE DESCRIPTOR POINTER. ; 保留描述符指针
STRSPA: JSR	GETSPA		;GET STRING SPACE. ; 获取字符串空间
	STXY	DSCTMP+1	;SAVE LOCATION. ; 保存位置
	STA	DSCTMP		;SAVE LENGTH. ; 保存长度
	RTS			;ALL DONE. ; 全部完成
;
; "STRLT2" TAKES THE STRING LITERAL WHOSE FIRST CHARACTER ; "STRLT2" 处理首字符由 [Y,A] 指向的字符串字面量
; IS POINTED TO BY [Y,A] AND BUILDS A DESCRIPTOR FOR IT. ; 并为其构建描述符。描述符最初在 "DSCTMP" 中构建
; THE DESCRIPTOR IS INITIALLY BUILT IN "DSCTMP", BUT "PUTNEW" ; 但 "PUTNEW" 会将其转移到临时位置并在 FACMO&LO 中
; TRANSFERS IT INTO A TEMPORARY AND LEAVES A POINTER ; 留下指向该临时位置的指针。除了零之外终止字符串的
; AT THE TEMPORARY IN FACMO&LO. THE CHARACTERS OTHER THAN ; 字符应在 "CHARAC" 和 "ENDCHR" 中设置。如果终止符是引号
; ZERO THAT TERMINATE THE STRING SHOULD BE SET UP IN "CHARAC" ; 则跳过引号。前导引号应在 JSR 前跳过。返回时
; AND "ENDCHR". IF THE TERMINATOR IS A QUOTE, THE QUOTE IS SKIPPED ; 字符串字面量后的字符由 [STRNG2] 指向
; OVER. LEADING QUOTES SHOULD BE SKIPPED BEFORE JSR. ON RETURN
; THE CHARACTER AFTER THE STRING LITERAL IS POINTED TO
; BY [STRNG2].
;
STRLIT: LDXI	34		;ASSUME STRING ENDS ON QUOTE. ; 假设字符串以引号结束
	STX	CHARAC		;存储到 CHARAC
	STX	ENDCHR		;存储到 ENDCHR
STRLT2: STWD	STRNG1		;SAVE POINTER TO STRING. ; 保存指向字符串的指针
	STWD	DSCTMP+1	;IN CASE NO STRCPY. ; 以防没有 STRCPY
	LDYI	255		;INITIALIZE CHARACTER COUNT. ; 初始化字符计数
STRGET: INY			;Y 加 1
	LDADY	STRNG1		;GET CHARACTER. ; 获取字符
	BEQ	STRFI1		;IF ZERO. ; 如果为零
	CMP	CHARAC		;THIS TERMINATOR? ; 是这个终止符吗？
	BEQ	STRFIN		;YES. ; 是
	CMP	ENDCHR		;比较 ENDCHR
	BNE	STRGET		;LOOK FURTHER. ; 继续查找
STRFIN: CMPI	34		;QUOTE? ; 引号？
	BEQ	STRFI2		;是，跳转到 STRFI2
STRFI1: CLC			;NO, BACK UP. ; 不清位，回退
STRFI2: STY	DSCTMP		;RETAIN COUNT. ; 保留计数
	TYA			;传输 Y 到 A
	ADC	STRNG1		;WISHING TO SET [TXTPTR]. ; 希望设置 [TXTPTR]
	STA	STRNG2		;存储到 STRNG2
	LDX	STRNG1+1	;加载 STRNG1+1
	BCC	STRST2		;若无进位，跳转到 STRST2
	INX			;X 加 1
STRST2: STX	STRNG2+1	;存储到 STRNG2+1
	LDA	STRNG1+1	;IF PAGE 0, COPY SINCE IT IS EITHER ; 如果在第 0 页，则复制，因为它要么是
				;A STRING CONSTANT IN BUF OR A STR$ ; BUF 中的字符串常量，要么是 STR$
				;RESULT IN LOFBUF ; LOFBUF 中的结果
IFN	BUFPAG,<		;如果定义了 BUFPAG
	BEQ	STRCP		;如果为零，跳转到 STRCP
	CMPI	BUFPAG>		;比较 BUFPAG
	BNE	PUTNEW		;不相等，跳转到 PUTNEW
STRCP:	TYA			;传输 Y 到 A
	JSR	STRINI		;初始化字符串
	LDXY	STRNG1		;加载 STRNG1
	JSR	MOVSTR		;MOVE STRING. ; 移动字符串
;
; SOME STRING FUNCTION IS RETURNING A RESULT IN DSCTMP. ; 某些字符串函数在 DSCTMP 中返回结果
; SETUP A TEMP DESCRIPTOR WITH DSCTMP IN IT. ; 用 DSCTMP 设置临时描述符
; PUT A POINTER TO THE DESCRIPTOR IN FACMO&LO AND FLAG THE ; 在 FACMO&LO 中放入指向描述符的指针并将结果标记为字符串类型
; RESULT AS TYPE STRING.
;
PUTNEW: LDX	TEMPPT		;POINTER TO FIRST FREE TEMP. ; 指向第一个空闲临时位置的指针
	CPXI	TEMPST+STRSIZ*NUMTMP ; 比较 TEMPST+STRSIZ*NUMTMP
	BNE	PUTNW1		;不相等，跳转到 PUTNW1
	LDXI	ERRST		;STRING TEMPORARY ERROR. ; 字符串临时错误
ERRGO2: JMP	ERROR		;GO TELL HIM. ; 去告诉他
PUTNW1: LDA	DSCTMP		;加载 DSCTMP
	STA	0,X		;存储到 0,X
	LDA	DSCTMP+1	;加载 DSCTMP+1
	STA	1,X		;存储到 1,X
	LDA	DSCTMP+2	;加载 DSCTMP+2
	STA	2,X		;存储到 2,X
	LDYI	0		;Y 清零
	STXY	FACMO		;存储到 FACMO
	STY	FACOV		;存储到 FACOV
	DEY			;Y 减 1
	STY	VALTYP		;TYPE IS "STRING". ; 类型为"字符串"
	STX	LASTPT		;SET POINTER TO LAST-USED TEMP. ; 设置指向最后使用的临时位置的指针
	INX			;X 加 1
	INX			;X 加 1
	INX			;X 加 1
	STX	TEMPPT		;SAVE POINTER TO NEXT TEMP IF ANY. ; 保存指向下一个临时位置的指针（如果有）
	RTS			;ALL DONE. ; 全部完成

;
; GETSPA - GET SPACE FOR CHARACTER STRING. ; GETSPA - 获取字符串空间
; MAY FORCE GARBAGE COLLECTION. ; 可能强制垃圾收集
;
; # OF CHARACTERS (BYTES) IN ACCA. ; ACCA 中的字符数（字节数）
; RETURNS WITH POINTER IN [Y,X]. OTHERWISE (IF CAN'T GET ; 返回时指针在 [Y,X] 中。否则（如果无法获取空间）
; SPACE) BLOWS OFF TO "OUT OF STRING SPACE" TYPE ERROR. ; 会跳转到"字符串空间不足"类型错误
; ALSO PRESERVES [ACCA] AND SETS [FRESPC]=[Y,X]=PNTR AT SPACE. ; 同时保留 [ACCA] 并设置 [FRESPC]=[Y,X]=指向空间的指针
;
GETSPA: LSR	GARBFL		;SIGNAL NO GARBAGE COLLECTION YET. ; 标记尚未进行垃圾收集
TRYAG2: PHA			;SAVE FOR LATER. ; 保存供后续使用
	EORI	255		;按位取反
	SEC			;ADD ONE TO COMPLETE NEGATION. ; 置位进位以完成取反
	ADC	FRETOP		;加 FRETOP
	LDY	FRETOP+1	;加载 FRETOP+1
	BCS	TRYAG3		;若有进位，跳转到 TRYAG3
	DEY			;Y 减 1
TRYAG3: CPY	STREND+1	;COMPARE HIGH ORDERS. ; 比较高位
	BCC	GARBAG		;MAKE ROOM FOR MORE. ; 腾出更多空间
	BNE	STRFRE		;SAVE NEW FRETOP. ; 保存新的 FRETOP
	CMP	STREND		;COMPARE LOW ORDERS. ; 比较低位
	BCC	GARBAG		;CLEAN UP. ; 清理
STRFRE: STWD	FRETOP		;SAVE NEW [FRETOP]. ; 保存新的 [FRETOP]
	STWD	FRESPC		;PUT IT THERE OLD MAN. ; 放在那里
	TAX			;PRESERVE A IN X. ; 在 X 中保留 A
	PLA			;GET COUNT BACK IN ACCA. ; 取回计数到 ACCA
	RTS			;ALL DONE. ; 全部完成
GARBAG: LDXI	ERROM		;"OUT OF STRING SPACE" ; "字符串空间不足"
	LDA	GARBFL		;加载 GARBFL
	BMI	ERRGO2		;如果为负，跳转到 ERRGO2
	JSR	GARBA2		;执行垃圾收集
	LDAI	128		;A 设为 128
	STA	GARBFL		;存储到 GARBFL
	PLA			;GET BACK STRING LENGTH. ; 取回字符串长度
	BNE	TRYAG2		;ALWAYS BRANCHES. ; 总是跳转
GARBA2:				;START FROM TOP DOWN. ; 从上到下开始
IFE	REALIO!DISKO,<		;如果未定义 REALIO 或 DISKO
	LDAI	7		;TYPE "BELL". ; 输出"响铃"
	JSR	OUTDO>		;调用 OUTDO
	LDX	MEMSIZ		;加载 MEMSIZ
	LDA	MEMSIZ+1	;加载 MEMSIZ+1
FNDVAR: STX	FRETOP		;LIKE SO. ; 像这样
	STA	FRETOP+1	;存储到 FRETOP+1
	LDYI	0		;Y 清零
	STY	GRBPNT+1	;存储到 GRBPNT+1
	STY	GRBPNT		;BOTH BYTES SET TO ZERO (FIX BUG) ; 两个字节都设为零（修复错误）
	LDWX	STREND		;加载 STREND
	STWX	GRBTOP		;存储到 GRBTOP
	LDWXI	TEMPST		;加载 TEMPST 地址
	STWX	INDEX1		;存储到 INDEX1
TVAR:	CMP	TEMPPT		;DONE WITH TEMPS? ; 临时变量处理完毕？
	BEQ	SVARS		;YEP. ; 是
	JSR	DVAR		;处理变量
	BEQ	TVAR		;LOOP. ; 循环
SVARS:	LDAI	6+ADDPRC	;A 设为 6+ADDPRC
	STA	FOUR6		;存储到 FOUR6
	LDWX	VARTAB		;GET START OF SIMPLE VARIABLES. ; 获取简单变量的起始
	STWX	INDEX1		;存储到 INDEX1
SVAR:	CPX	ARYTAB+1	;DONE WITH SIMPLE VARIABLES? ; 简单变量处理完毕？
	BNE	SVARGO		;NO. ; 否
	CMP	ARYTAB		;比较 ARYTAB
	BEQ	ARYVAR		;YEP. ; 是
SVARGO: JSR	DVARS		;DO IT , AGAIN. ; 处理它，再次
	BEQ	SVAR		;LOOP. ; 循环
ARYVAR: STWX	ARYPNT		;SAVE FOR ADDITION. ; 保存供添加
	LDAI	STRSIZ		;A 设为 STRSIZ
	STA	FOUR6		;存储到 FOUR6
ARYVA2: LDWX	ARYPNT		;GET THE POINTER TO VARIABLE. ; 获取指向变量的指针
ARYVA3: CPX	STREND+1	;DONE WITH ARRAYS? ; 数组处理完毕？
	BNE	ARYVGO		;NO. ; 否
	CMP	STREND		;比较 STREND
	JEQ	GRBPAS		;YES, GO FINISH UP. ; 是，去完成
ARYVGO: STWX	INDEX1		;存储到 INDEX1
	LDYI	1-ADDPRC	;Y 设为 1-ADDPRC
IFN	ADDPRC,<		;如果定义了 ADDPRC
	LDADY	INDEX1		;加载 INDEX1,Y
	TAX			;传输到 X
	INY>			;Y 加 1
	LDADY	INDEX1		;加载 INDEX1,Y
	PHP			;保存状态
	INY			;Y 加 1
	LDADY	INDEX1		;加载 INDEX1,Y
	ADC	ARYPNT		;加 ARYPNT
	STA	ARYPNT		;FORM POINTER TO NEXT ARRAY VAR. ; 形成指向下一个数组变量的指针
	INY			;Y 加 1
	LDADY	INDEX1		;加载 INDEX1,Y
	ADC	ARYPNT+1	;加 ARYPNT+1
	STA	ARYPNT+1	;存储到 ARYPNT+1
	PLP			;恢复状态
	BPL	ARYVA2		;如果为正，跳转到 ARYVA2
IFN	ADDPRC,<		;如果定义了 ADDPRC
	TXA			;传输 X 到 A
	BMI	ARYVA2>		;如果为负，跳转到 ARYVA2
	INY			;Y 加 1
	LDADY	INDEX1		;加载 INDEX1,Y
	LDYI	0		;RESET INDEX Y. ; 重置索引 Y
	ASL	A,		;左移
	ADCI	5		;CARRY IS OFF AND OFF AFTER ADD. ; 进位清除且在加法后保持清除
	ADC	INDEX1		;加 INDEX1
	STA	INDEX1		;存储到 INDEX1
	BCC	ARYGET		;若无进位，跳转到 ARYGET
	INC	INDEX1+1	;INDEX1+1 加 1
ARYGET: LDX	INDEX1+1	;加载 INDEX1+1
ARYSTR: CPX	ARYPNT+1	;END OF THE ARRAY? ; 数组结束？
	BNE	GOGO		;NO. ; 否
	CMP	ARYPNT		;比较 ARYPNT
	BEQ	ARYVA3		;YES. ; 是
GOGO:	JSR	DVAR		;处理变量
	BEQ	ARYSTR		;CYCLE. ; 循环
DVARS:				;处理简单变量
IFN	INTPRC,<		;如果定义了 INTPRC
	LDADY	INDEX1		;加载 INDEX1,Y
	BMI	DVARTS>		;如果为负，跳转到 DVARTS
	INY			;Y 加 1
	LDADY	INDEX1		;加载 INDEX1,Y
	BPL	DVARTS		;如果为正，跳转到 DVARTS
	INY			;Y 加 1
DVAR:	LDADY	INDEX1		;IS LENGTH=0? ; 长度=0？
	BEQ	DVARTS		;YES, RETURN. ; 是，返回
	INY			;Y 加 1
	LDADY	INDEX1		;GET LOW(ADR). ; 获取地址低字节
	TAX			;传输到 X
	INY			;Y 加 1
	LDADY	INDEX1		;加载 INDEX1,Y
	CMP	FRETOP+1	;COMPARE HIGHS. ; 比较高位
	BCC	DVAR2		;IF THIS STRING'S PNTR .GE. [FRETOP] ; 如果此字符串指针 >= [FRETOP]
	BNE	DVARTS		;NO NEED TO MESS WITH IT FURTHER. ; 无需进一步处理
	CPX	FRETOP		;COMPARE LOWS. ; 比较低位
	BCS	DVARTS		;如果大于等于，跳转到 DVARTS
DVAR2:	CMP	GRBTOP+1	;比较 GRBTOP+1
	BCC	DVARTS		;IF THIS STRING IS BELOW PREVIOUS, ; 如果此字符串低于之前的
				;FORGET IT. ; 忽略它
	BNE	DVAR3		;不相等，跳转到 DVAR3
	CPX	GRBTOP		;COMPARE LOW ORDERS. ; 比较低位
	BCC	DVARTS		;[X,A] .LE. [GRBTOP]. ; [X,A] <= [GRBTOP]
DVAR3:	STX	GRBTOP		;存储到 GRBTOP
	STA	GRBTOP+1	;存储到 GRBTOP+1
	LDWX	INDEX1		;加载 INDEX1
	STWX	GRBPNT		;存储到 GRBPNT
	LDA	FOUR6		;加载 FOUR6
	STA	SIZE		;存储到 SIZE
DVARTS: LDA	FOUR6		;加载 FOUR6
	CLC			;清进位
	ADC	INDEX1		;加 INDEX1
	STA	INDEX1		;存储到 INDEX1
	BCC	GRBRTS		;若无进位，跳转到 GRBRTS
	INC	INDEX1+1	;INDEX1+1 加 1
GRBRTS: LDX	INDEX1+1	;加载 INDEX1+1
	LDYI	0		;Y 清零
	RTS			;DONE. ; 完成
;
; HERE WHEN MADE ONE COMPLETE PASS THROUGH STRING VARIABLES. ; 当完成一次字符串变量遍历时到这里
;
GRBPAS: LDA	GRBPNT+1	;VARIABLE POINTER. ; 变量指针高字节
	ORA	GRBPNT		;或低字节
	BEQ	GRBRTS		;ALL DONE. ; 全部完成
	LDA	SIZE		;加载 SIZE
	ANDI	4		;LEAVES C OFF. ; 保留位，进位清除
	LSR	A,		;右移
	TAY			;传输到 Y
	STA	SIZE		;存储到 SIZE
	LDADY	GRBPNT		;加载 GRBPNT,Y
				;NOTE: GRBTOP=LOWTR SO NO NEED TO SET LOWTR. ; 注意：GRBTOP=LOWTR，因此无需设置 LOWTR
	ADC	LOWTR		;加 LOWTR
	STA	HIGHTR		;存储到 HIGHTR
	LDA	LOWTR+1		;加载 LOWTR+1
	ADCI	0		;加进位
	STA	HIGHTR+1	;存储到 HIGHTR+1
	LDWX	FRETOP		;加载 FRETOP
	STWX	HIGHDS		;WHERE IT ALL GOES. ; 目标位置
	JSR	BLTUC		;块传输
	LDY	SIZE		;加载 SIZE
	INY			;Y 加 1
	LDA	HIGHDS		;GET POSITION OF START OF RESULT. ; 获取结果起始位置
	STADY	GRBPNT		;存储到 GRBPNT,Y
	TAX			;传输到 X
	INC	HIGHDS+1	;HIGHDS+1 加 1
	LDA	HIGHDS+1	;加载 HIGHDS+1
	INY			;Y 加 1
	STADY	GRBPNT		;CHANGE ADDR OF STRING IN VAR. ; 更改变量中的字符串地址
	JMP	FNDVAR		;GO TO FNDVAR WITH SOMETHING FOR ; 带着一些东西去 FNDVAR
				;[FRETOP]. ; [FRETOP]
;
; THE FOLLOWING ROUTINE CONCATENATES TWO STRINGS. ; 以下例程连接两个字符串
; THE FAC CONTAINS THE FIRST ONE AT THIS POINT. ; 此时 FAC 包含第一个字符串
; [TXTPTR] POINTS TO THE + SIGN. ; [TXTPTR] 指向 + 号
;
CAT:	LDA	FACLO		;PSH HIGH ORDER ONTO STACK. ; 将高阶压栈
	PHA			;压栈
	LDA	FACMO		;AND THE LOW. ; 以及低阶
	PHA			;压栈
	JSR	EVAL		;CAN COME BACK HERE SINCE ; 可以回到这里，因为
				;OPERATOR IS KNOWN. ; 操作符已知
	JSR	CHKSTR		;RESULT MUST BE STRING. ; 结果必须是字符串
	PLA			;弹出
	STA	STRNG1		;GET HIGH ORDER OF OLD DESC. ; 获取旧描述符的高阶
	PLA			;弹出
	STA	STRNG1+1	;存储到 STRNG1+1
	LDYI	0		;Y 清零
	LDADY	STRNG1		;GET LENGTH OF OLD STRING. ; 获取旧字符串长度
	CLC			;清进位
	ADCDY	FACMO		;加 FACMO,Y
	BCC	SIZEOK		;RESULT IS LESS THAN 256. ; 结果小于 256
	LDXI	ERRLS		;ERROR "LONG STRING". ; 错误"字符串过长"
	JMP	ERROR		;跳转到错误处理
SIZEOK: JSR	STRINI		;INITIALIZE STRING. ; 初始化字符串
	JSR	MOVINS		;MOVE IT. ; 移动它
	LDWD	DSCPNT		;GET POINTER TO SECOND. ; 获取指向第二个的指针
	JSR	FRETMP		;FREE IT. ; 释放它
	JSR	MOVDO		;移动操作
	LDWD	STRNG1		;加载 STRNG1
	JSR	FRETMP		;释放临时变量
	JSR	PUTNEW		;放入新临时变量
	JMP	TSTOP		;"CAT" REENTERS FORM EVAL AT TSTOP. ; "CAT" 在 TSTOP 重新进入公式求值

MOVINS: LDYI	0		;GET ADDR OF STRING. ; 获取字符串地址
	LDADY	STRNG1		;加载 STRNG1,Y
	PHA			;压栈
	INY			;Y 加 1
	LDADY	STRNG1		;加载 STRNG1,Y
	TAX			;传输到 X
	INY			;Y 加 1
	LDADY	STRNG1		;加载 STRNG1,Y
	TAY			;传输到 Y
	PLA			;弹出
MOVSTR: STXY	INDEX		;存储到 INDEX
MOVDO:	TAY			;传输到 Y
	BEQ	MVDONE		;如果为零，跳转到 MVDONE
	PHA			;压栈
MOVLP:	DEY			;Y 减 1
	LDADY	INDEX		;加载 INDEX,Y
	STADY	FRESPC		;存储到 FRESPC,Y
QMOVE:	TYA			;传输 Y 到 A
	BNE	MOVLP		;如果不为零，继续循环
	PLA			;弹出
MVDONE: CLC			;清进位
	ADC	FRESPC		;加 FRESPC
	STA	FRESPC		;存储到 FRESPC
	BCC	MVSTRT		;若无进位，跳转到 MVSTRT
	INC	FRESPC+1	;FRESPC+1 加 1
MVSTRT: RTS			;返回
;
; "FRETMP" IS PASSED A STRING DESCRIPTOR PNTR IN [Y,A]. ; "FRETMP" 通过 [Y,A] 传递字符串描述符指针
; A CHECK IS MADE TO SEE IF THE STRING DESCRIPTOR POINTS TO THE LAST ; 检查该字符串描述符是否指向 PUTNEW 分配的最后一个临时描述符
; TEMPORARY DESCRIPTOR ALLOCATED BY PUTNEW. 
; IF SO, THE TEMPORARY IS FREED UP BY THE UPDATING OF [TEMPPT]. ; 如果是，则通过更新 [TEMPPT] 释放该临时变量
; IF A TEMP IS FREED UP, A FURTHER CHECK SEES IF THE STRING DATA THAT ; 如果临时变量被释放，进一步检查该字符串临时变量指向的字符串数据
; THAT STRING TEMP PNT'D TO IS THE LOWEST PART OF STRING SPACE IN USE. 
; IF SO, [FRETOP] IS UPDATED TO REFLECT THE FACT THE FACT THAT THE SPACE ; 是否正在使用的字符串空间的最低部分
; IS NO LONGER IN USE. ; 如果是，则更新 [FRETOP] 以反映该空间不再使用的事实
; THE ADDR OF THE ACTUAL STRING IS RETURNED IN [Y,X] AND ; 实际字符串的地址在 [Y,X] 中返回，其长度在 ACCA 中
; ITS LENGTH IN ACCA.
;
FRESTR: JSR	CHKSTR		;MAKE SURE ITS A STRING. ; 确保是字符串
FREFAC: LDWD	FACMO		;FREE UP STR PNT'D TO BY FAC. ; 释放 FAC 指向的字符串
FRETMP: STWD	INDEX		;GET LENGTH FOR LATER. ; 获取长度供后续使用
	JSR	FRETMS		;FREE UP THE TEMPORARY DESC. ; 释放临时描述符
	PHP			;SAVE CODES. ; 保存状态
	LDYI	0		;PREP TO GET STUFF. ; 准备获取内容
	LDADY	INDEX		;GET COUNT AND ; 获取计数并
	PHA			;SAVE IT. ; 保存它
	INY			;Y 加 1
	LDADY	INDEX		;加载 INDEX,Y
	TAX			;SAVE LOW ORDER. ; 保存低阶
	INY			;Y 加 1
	LDADY	INDEX		;加载 INDEX,Y
	TAY			;SAVE HIGH ORDER. ; 保存高阶
	PLA			;弹出
	PLP			;RETURN STATUS. ; 恢复状态
	BNE	FRETRT		;如果不为零，跳转到 FRETRT
	CPY	FRETOP+1	;STRING IS LAST ONE IN? ; 字符串是最后一个吗？
	BNE	FRETRT		;不相等，跳转到 FRETRT
	CPX	FRETOP		;比较 FRETOP
	BNE	FRETRT		;不相等，跳转到 FRETRT
	PHA			;压栈
	CLC			;清进位
	ADC	FRETOP		;加 FRETOP
	STA	FRETOP		;存储到 FRETOP
	BCC	FREPLA		;若无进位，跳转到 FREPLA
	INC	FRETOP+1	;FRETOP+1 加 1
FREPLA: PLA			;GET COUNT BACK. ; 取回计数
FRETRT: STXY	INDEX		;SAVE FOR LATER USE. ; 保存供后续使用
	RTS			;返回
FRETMS: CPY	LASTPT+1	;LAST ENTRY TO TEMP? ; 最后一个临时条目？
	BNE	FRERTS		;不相等，跳转到 FRERTS
	CMP	LASTPT		;比较 LASTPT
	BNE	FRERTS		;不相等，跳转到 FRERTS
	STA	TEMPPT		;存储到 TEMPPT
	SBCI	STRSIZ		;POINT TO LAST ONE. ; 指向最后一个
	STA	LASTPT		;UPDATE TEMP PNTR. ; 更新临时指针
	LDYI	0		;ALSO CLEARS ZFLG SO WE DO REST OF FRETMP. ; 同时清零 Z 标志以便执行 FRETMP 的其余部分
FRERTS: RTS			;ALL DONE. ; 全部完成
;
; CHR$(#) CREATES A STRING WHICH CONTAINS AS ITS ONLY ; CHR$(#) 创建一个字符串，该字符串包含作为其唯一字符的
; CHARACTER THE ASCII EQUIVALENT OF THE INTEGER ARGUMENT (#) ; 整数参数 (#) 的 ASCII 等价物，该参数必须 < 255
; WHICH MUST BE .LT. 255.
;
CHR:	JSR	CONINT		;GET INTEGER IN RANGE. ; 获取范围内的整数
	TXA			;传输 X 到 A
	PHA			;压栈
	LDAI	1		;ONE-CHARACTER STRING. ; 单字符字符串
	JSR	STRSPA		;GET SPACE FOR STRING. ; 获取字符串空间
	PLA			;弹出
	LDYI	0		;Y 清零
	STADY	DSCTMP+1	;存储到 DSCTMP+1,Y
	PLA			;GET RID OF "CHKNUM" RETURN ADDR. ; 丢弃 "CHKNUM" 返回地址
	PLA			;弹出
RLZRET: JMP	PUTNEW		;SETUP FAC TO POINT TO DESC. ; 设置 FAC 指向描述符
;
; THE FOLLOWING IS THE LEFT$($,#) FUNCTION. ; 以下是 LEFT$($,#) 函数
; IT TAKES THE LEFTMOST # CHARACTERS OF THE STRING. ; 它取字符串的最左边 # 个字符
; IF # .GT. THE LEN OF THE STRING, IT RETURNS THE WHOLE STRING. ; 如果 # > 字符串长度，则返回整个字符串
;
LEFT:	JSR	PREAM		;TEST PARAMETERS. ; 测试参数
	CMPDY	DSCPNT		;比较 DSCPNT,Y
	TYA			;传输 Y 到 A
RLEFT:	BCC	RLEFT1		;如果小于，跳转到 RLEFT1
	LDADY	DSCPNT		;加载 DSCPNT,Y
	TAX			;PUT LENGTH INTO X. ; 将长度放入 X
	TYA			;ZERO A, THE OFFSET. ; 清零 A，偏移量
RLEFT1: PHA			;SAVE OFFSET. ; 保存偏移量
RLEFT2: TXA			;传输 X 到 A
RLEFT3: PHA			;SAVE LENGTH. ; 保存长度
	JSR	STRSPA		;GET SPACE. ; 获取空间
	LDWD	DSCPNT		;加载 DSCPNT
	JSR	FRETMP		;释放临时变量
	PLA			;弹出
	TAY			;传输到 Y
	PLA			;弹出
	CLC			;清进位
	ADC	INDEX		;COMPUTE WHERE TO COPY. ; 计算复制位置
	STA	INDEX		;存储到 INDEX
	BCC	PULMOR		;若无进位，跳转到 PULMOR
	INC	INDEX+1		;INDEX+1 加 1
PULMOR: TYA			;传输 Y 到 A
	JSR	MOVDO		;GO MOVE IT. ; 去移动它
	JMP	PUTNEW		;放入新临时变量
RIGHT:	JSR	PREAM		;测试参数
	CLC			;[LENGTH DES'D]-[LENGTH]-1. ; [所需长度]-[长度]-1
	SBCDY	DSCPNT		;减去 DSCPNT,Y
	EORI	255		;NEGATE. ; 取反
	JMP	RLEFT		;跳转到 RLEFT
;
; MID ($,#) RETURNS STRING WITH CHARS FROM # POSITION ; MID ($,#) 返回从 # 位置开始的字符串
; ONWARD. IF # .GT. LEN ($) THEN RETURN NULL STRING. ; 如果 # > LEN ($) 则返回空字符串
; MID ($,#,#) RETURNS STRING WITH CHARACTERS FROM ; MID ($,#,#) 返回从 # 位置开始的 #2 个字符的字符串
; # POSITION FOR #2 CHARACTERS. IF #2 GOES PAST END OF STRING ; 如果 #2 超过字符串末尾，则返回尽可能多的字符
; RETURN AS MUCH AS POSSIBLE.
;
MID:	LDAI	255		;DEFAULT. ; 默认值
	STA	FACLO		;SAVE FOR LATER COMPARE. ; 保存供后续比较
	JSR	CHRGOT		;GET CURRENT CHARACTER. ; 获取当前字符
	CMPI	41		;IS IT A RIGHT PAREN )? ; 是右括号 ) 吗？
	BEQ	MID2		;NO THIRD PARAM. ; 无第三个参数
	JSR	CHKCOM		;MUST HAVE COMMA. ; 必须有逗号
	JSR	GETBYT		;GET THE LENGTH INTO "FACLO". ; 获取长度到 "FACLO"
MID2:	JSR	PREAM		;CHECK IT OUT. ; 检查
	BEQ	GOFUC		;THERE IS NO POSTION 0 ; 没有位置 0
	DEX			;COMPUTE OFFSET. ; 计算偏移量
	TXA			;传输 X 到 A
	PHA			;PRSERVE AWHILE. ; 暂时保存
	CLC			;清进位
	LDXI	0		;X 清零
	SBCDY	DSCPNT		;GET LENGTH OF WHAT'S LEFT. ; 获取剩余长度
	BCS	RLEFT2		;GIVE NULL STRING. ; 提供空字符串
	EORI	255		;IN SUB C WAS 0 SO JUST COMPLEMENT. ; 减法中 C 为 0，因此只需取补
	CMP	FACLO		;GREATER THAN WHAT'S DESIRED? ; 大于所需吗？
	BCC	RLEFT3		;NO, COPY THAT MUCH. ; 否，复制那么多
	LDA	FACLO		;GET LENGTH OF WHAT'S DESIRED. ; 获取所需长度
	BCS	RLEFT3		;COPY IT. ; 复制它

;
; USED BY RIGHT$, LEFT$, MID$ FOR PARAMETER CHECKING AND SETUP. ; 被 RIGHT$, LEFT$, MID$ 用于参数检查和设置
;
PREAM:	JSR	CHKCLS		;PARAM LIST SHOULD END. ; 参数列表应结束
	PLA			;GET THE RETURN ADDRESS INTO ; 获取返回地址到
	TAY			;[JMPER+1,Y] ; [JMPER+1,Y]
	PLA			;弹出
	STA	JMPER+1		;存储到 JMPER+1
	PLA			;GET RID OF FINGO'S JSR RET ADDR. ; 丢弃 FINGO 的 JSR 返回地址
	PLA			;弹出
	PLA			;GET LENGTH. ; 获取长度
	TAX			;传输到 X
	PULWD	DSCPNT		;弹出到 DSCPNT
	LDA	JMPER+1		;PUT RETURN ADDRESS BACK ON ; 将返回地址放回
	PHA			;压栈
	TYA			;传输 Y 到 A
	PHA			;压栈
	LDYI	0		;Y 清零
	TXA			;传输 X 到 A
	RTS			;返回
;
; THE FUNCTION LEN($) RETURNS THE LENGTH OF THE STRING ; LEN($) 函数返回作为参数传递的字符串的长度
; PASSED AS AN ARGUMENT.
;
LEN:	JSR	LEN1		;调用 LEN1
	JMP	SNGFLT		;浮点化
LEN1:	JSR	FRESTR		;FREE UP STRING. ; 释放字符串
	LDXI	0		;X 清零
	STX	VALTYP		;FORCE NUMERIC. ; 强制为数字
	TAY			;SET CODES ON LENGTH. ; 根据长度设置状态
	RTS			;DONE. ; 完成
;
; THE FOLLOWING IS THE ASC($) FUNCTION. IT RETURNS ; 以下是 ASC($) 函数。它返回一个整数，该整数是十进制的 ASCII 等价物
; AN INTEGER WHICH IS THE DECIMAL ASCII EQUIVALENT.
;
ASC:	JSR	LEN1		;调用 LEN1
	BEQ	GOFUC		;NULL STRING, BAD ARG. ; 空字符串，错误参数
	LDYI	0		;Y 清零
	LDADY	INDEX1		;GET CHARACTER. ; 获取字符
	TAY			;传输到 Y
	JMP	SNGFLT		;浮点化
GOFUC:	JMP	FCERR		;YES. ; 是，跳转到 FCERR

GTBYTC: JSR	CHRGET		;获取字符
GETBYT: JSR	FRMNUM		;READ FORMULA INTO FAC. ; 将公式读入 FAC
CONINT: JSR	POSINT		;CONVERT THE FAC TO A SINGLE BYTE INT. ; 将 FAC 转换为单字节整数
	LDX	FACMO		;加载 FACMO
	BNE	GOFUC		;RESULT MUST BE .LE. 255. ; 结果必须 <= 255
	LDX	FACLO		;加载 FACLO
CHRGO2: JMP	CHRGOT		;SET CONDITION CODES ON TERMINATOR. ; 根据终止符设置条件码
;
; THE "VAL" FUNCTION TAKES A STRING AND TURNS IT INTO ; "VAL" 函数接受一个字符串并通过解释 ASCII 数字等
; A NUMBER BY INTERPRETING THE ASCII DIGITS ETCQ ; 将其转换为数字。除了必须通过替换字符串后的字符
; EXCEPT FOR THE PROBLEM THAT A TERMINATOR MUST BE SUPPLIED ; 来提供终止符的问题外，VAL 仅仅是对浮点输入 ("FIN") 的调用
; BY REPLACING THE CHARACTER BEYOND THE STRING, VAL IS MERELY
; A CALL TO FLOATING POINT INPUT ("FIN").
;
VAL:	JSR	LEN1		;DO SETUP. SET RESULT=NUMERIC. ; 设置。设置结果=数字
	JEQ	ZEROFC		;ZERO THE FAC ON A NULL STRING ; 空字符串时清零 FAC
	LDXY	TXTPTR		;加载 TXTPTR
	STXY	STRNG2		;SAVE FOR LATER. ; 保存供后续使用
	LDX	INDEX1		;加载 INDEX1
	STX	TXTPTR		;存储到 TXTPTR
	CLC			;清进位
	ADC	INDEX1		;加 INDEX1
	STA	INDEX2		;存储到 INDEX2
	LDX	INDEX1+1	;加载 INDEX1+1
	STX	TXTPTR+1	;存储到 TXTPTR+1
	BCC	VAL2		;NO CARRY, NO INC. ; 无进位，不增加
	INX			;X 加 1
VAL2:	STX	INDEX2+1	;存储到 INDEX2+1
	LDYI	0		;Y 清零
	LDADY	INDEX2		;PRESERVE CHARACTER. ; 保留字符
	PHA			;压栈
	LDAI	0		;SET A TERMINATOR. ; 设置终止符
	STADY	INDEX2		;存储到 INDEX2,Y
	JSR	CHRGOT		;GET CHARACTER PNT'D TO AND SET FLAGS. ; 获取指向的字符并设置标志
	JSR	FIN		;浮点输入
	PLA			;GET PRES'D CHARACTER. ; 取回保留的字符
	LDYI	0		;Y 清零
	STADY	INDEX2		;STUFF IT BACK. ; 放回
ST2TXT: LDXY	STRNG2		;加载 STRNG2
	STXY	TXTPTR		;存储到 TXTPTR
VALRTS: RTS			;ALL DONE WITH STRINGS. ; 字符串处理全部完成
PAGE				;分页
SUBTTL	PEEK, POKE, AND FNWAIT. ; 子标题：PEEK、POKE 和 FNWAIT

GETNUM: JSR	FRMNUM		;GET ADDRESS. ; 获取地址
	JSR	GETADR		;GET THAT LOCATION. ; 获取该位置
COMBYT: JSR	CHKCOM		;CHECK FOR A COMMA. ; 检查逗号
	JMP	GETBYT		;GET SOMETHING TO STORE AND RETURN. ; 获取要存储的内容并返回
GETADR: LDA	FACSGN		;EXAMINE SIGN. ; 检查符号
	BMI	GOFUC		;FUNCTION CALL ERROR. ; 函数调用错误
	LDA	FACEXP		;EXAMINE EXPONENT. ; 检查指数
	CMPI	145		;比较 145
	BCS	GOFUC		;FUNCTION CALL ERROR. ; 函数调用错误
	JSR	QINT		;INTEGERIZE IT. ; 整数化
	LDWD	FACMO		;加载 FACMO
	STY	POKER		;存储到 POKER
	STA	POKER+1		;存储到 POKER+1
	RTS			;IT'S DONE !. ; 完成！

PEEK:	PSHWD	POKER		;保存 POKER
	JSR	GETADR		;获取地址
	LDYI	0		;Y 清零
IFE	REALIO-3,<		;如果 REALIO=3
	CMPI	ROMLOC/256	;IF WITHIN BASIC, ; 如果在 BASIC 内
	BCC	GETCON		;如果小于，跳转到 GETCON
	CMPI	LASTWR/256	;比较 LASTWR/256
	BCC	DOSGFL>		;GIVE HIM ZERO FOR AN ANSWER. ; 给他零作为答案
GETCON: LDADY	POKER		;GET THAT BYTE. ; 获取该字节
	TAY			;传输到 Y
DOSGFL: PULWD	POKER		;恢复 POKER
	JMP	SNGFLT		;FLOAT IT. ; 浮点化

POKE:	JSR	GETNUM		;获取数字
	TXA			;传输 X 到 A
	LDYI	0		;Y 清零
	STADY	POKER		;STORE VALUE AWAY. ; 存储值
	RTS			;SCANNED  EVERYTHING. ; 已扫描所有内容

; THE WAIT LOCATION,MASK1,MASK2 STATEMENT WAITS UNTIL THE CONTENTS ; WAIT 位置,掩码1,掩码2 语句等待，直到位置的内容
; OF LOCATION IS NONZERO WHEN XORED WITH MASK2 ; 与 MASK2 异或后然后与 MASK1 与操作的结果非零
; AND THEN ANDED WITH MASK1. IF MASK2 IS NOT PRESENT, IT ; 如果 MASK2 不存在，则假定为零
; IS ASSUMED TO BE ZERO.

FNWAIT: JSR	GETNUM		;获取数字
	STX	ANDMSK		;存储到 ANDMSK
	LDXI	0		;X 清零
	JSR	CHRGOT		;获取当前字符
	BEQ	ZSTORDO		;如果为零，跳转到 ZSTORDO
	JSR	COMBYT		;GET MASK2. ; 获取 MASK2
STORDO: STX	EORMSK		;存储到 EORMSK
	LDYI	0		;Y 清零
WAITER: LDADY	POKER		;加载 POKER,Y
	EOR	EORMSK		;异或 EORMSK
	AND	ANDMSK		;与 ANDMSK
	BEQ	WAITER		;如果为零，继续等待
ZERRTS: RTS			;GOT A NONZERO. ; 得到非零值
SUBTTL FLOATING POINT MATH PACKAGE CONFIGURATION. ; 子标题：浮点数学包配置

RADIX	8			;!!!! ALERT !!!! ; ！！！注意！！！
				;THROUGHOUT THE MATH PACKAGE. ; 在整个数学包中
COMMENT %   ; 注释 %
THE FLOATING POINT FORMAT IS AS FOLLOWS: ; 浮点格式如下：

THE SIGN IS THE FIRST BIT OF THE MANTISSA. ; 符号位是尾数的第一位。
THE MANTISSA IS 24 BITS LONG. ; 尾数长度为24位。
THE BINARY POINT IS TO THE LEFT OF THE MSB. ; 二进制小数点位于最高有效位(MSB)的左侧。
NUMBER = MANTISSA * 2 ^ EXPONENT. ; 数值 = 尾数 * 2 ^ 指数。
THE MANTISSA IS POSITIVE WITH A ONE ASSUMED TO BE WHERE THE SIGN BIT IS. ; 尾数为正数，且假定符号位处为1。
THE SIGN OF THE EXPONENT IS THE FIRST BIT OF THE EXPONENT. ; 指数的符号是指数的第一位。
THE EXPONENT IS STORED IN EXCESS 200, I.E. WITH A BIAS OF +200. ; 指数以偏移200形式存储，即带有+200的偏置。
SO, THE EXPONENT IS A SIGNED 8-BIT NUMBER WITH 200 ADDED TO IT. ; 因此，指数是一个有符号的8位数，并加上了200。
AN EXPONENT OF ZERO MEANS THE NUMBER IS ZERO. ; 指数为零表示该数字为零。
THE OTHER BYTES MAY NOT BE ASSUMED TO BE ZERO. ; 不能假定其他字节为零。
TO KEEP THE SAME NUMBER IN THE FAC WHILE SHIFTING, ; 为了在移位时保持FAC中的数字不变：
	TO SHIFT RIGHT, EXP:=EXP+1 ; 	右移时，EXP:=EXP+1
	TO SHIFT LEFT,	EXP:=EXP-1 ; 	左移时，EXP:=EXP-1

IN MEMORY THE NUMBER LOOKS LIKE THIS: ; 在内存中，数字的存储形式如下：
	[THE EXPONENT AS A SIGNED NUMBER +200] ; 	[作为有符号数字+200的指数]
	[THE SIGN BIT IN 7, BITS 2-8 OF MANTISSA ARE IN BITS 6-0]. ; 	[第7位为符号位，尾数的第2-8位位于第6-0位]。
		(REMEMBER BIT 1 OF MANTISSA IS ALWAYS A ONE.) ; 		(记住尾数的第1位总是1。)
	[BITS 9-16 OF THE MANTISSA] ; 	[尾数的第9-16位]
	[BITS 17-24] OF THE MANTISSA] ; 	[尾数的第17-24位]

ARITHMETIC ROUTINE CALLING CONVENTIONS: ; 算术例程调用约定：

FOR ONE ARGUMENT FUNCTIONS: ; 对于单参数函数：
	THE ARGUMENT IS IN THE FAC. ; 	参数在FAC中。
	THE RESULT IS LEFT IN THE FAC. ; 	结果留在FAC中。
FOR TWO ARGUMENT OPERATIONS: ; 对于双参数操作：
	THE FIRST ARGUMENT IS IN ARG (ARGEXP,HO,MO,LO AND ARGSGN). ; 	第一个参数在ARG中(ARGEXP,HO,MO,LO和ARGSGN)。
	THE SECOND ARGUMENT IS IN THE FAC. ; 	第二个参数在FAC中。
	THE RESULT IS LEFT IN THE FAC. ; 	结果留在FAC中。

THE "T" ENTRY POINTS TO THE TWO-ARGUMENT OPERATIONS HAVE BOTH ARGUMENTS ; 双参数操作的"T"入口点将两个参数
SETUP IN THE RESPECTIVE REGISTERS. BEFORE CALLING ARG MAY HAVE BEEN ; 设置在各自的寄存器中。在调用之前，ARG可能已经
POPPED OFF THE STACK AND INTO ARG, FOR EXAMPLE. ; 从堆栈弹出并放入ARG，例如。
THE OTHER ENTRY POINT ASSUMES [Y,A] POINTS TO THE ARGUMENT ; 另一个入口点假定[Y,A]指向内存中某处的参数。
SOMEWHERE IN MEMORY. IT IS UNPACKED INTO ARG BY "CONUPK". ; 它通过"CONUPK"解包到ARG中。

ON THE STACK, THE SGN IS PUSHED ON FIRST, THE LO,MO,HO AND FINALLY EXP. ; 在堆栈上，首先压入的是SGN，然后是LO,MO,HO，最后是EXP。
NOTE ALL THINGS ARE KEPT UNPACKED IN ARG, FAC AND ON THE STACK. ; 注意所有内容在ARG、FAC和堆栈上都保持解包状态。

IT IS ONLY WHEN SOMETHING IS STORED AWAY THAT IT IS PACKED TO FOUR ; 只有当某些内容被存储 away 时，它才会被打包成四个字节。
BYTES. THE UNPACKED FORMAT HAS A SGN BYTE REFLECTING THE SIGN OF THE ; 解包的格式有一个SGN字节反映数字的符号
NUMBER (POSITIVE=0, NEGATIVE=-1) A HO,MO AND LO WITH THE HIGH BIT ; (正数=0，负数=-1)，以及HO,MO和LO，且HO的最高位被打开。
OF THE HO TURNED ON. THE EXP IS THE SAME AS STORED FORMAT. ; EXP与存储格式相同。
THIS IS DONE FOR SPEED OF OPERATION. ; 这样做的目的是为了提高操作速度。
%
PAGE				;分页
SUBTTL	FLOATING POINT ADDITION AND SUBTRACTION. ; 子标题：浮点加法和减法
FADDH:	LDWDI	FHALF		;ENTRY TO ADD 1/2. ; 入口以加 1/2
	JMP	FADD		;UNPACK AND GO ADD IT. ; 解包并去加它
FSUB:	JSR	CONUPK		;UNPACK ARGUMENT INTO ARG. ; 将参数解包到 ARG
FSUBT:	LDA	FACSGN		;加载 FACSGN
	EORI	377		;COMPLEMENT IT. ; 取反它
	STA	FACSGN		;存储到 FACSGN
	EOR	ARGSGN		;COMPLEMENT ARISGN. ; 取反 ARISGN
	STA	ARISGN		;存储到 ARISGN
	LDA	FACEXP		;SET CODES ON FACEXP. ; 根据 FACEXP 设置状态
	JMP	FADDT		;[Y]=ARGEXP.. ; [Y]=ARGEXP..
	XLIST			;禁止列表
.XCREF				;禁止交叉引用
IFN	REALIO-3,<ZSTORDO=STORDO> ; 如果 REALIO≠3，则 ZSTORDO=STORDO
IFE	REALIO-3,<		;如果 REALIO=3
ZSTORD:!	LDA	POKER	;加载 POKER
	CMPI	146		;比较 146
	BNE	STORDO		;不相等，跳转到 STORDO
	LDA	POKER+1		;加载 POKER+1
	SBCI	31		;减去 31
	BNE	STORDO		;不相等，跳转到 STORDO
	STA	POKER		;存储到 POKER
	TAY			;传输到 Y
	LDAI	200		;A 设为 200
	STA	POKER+1		;存储到 POKER+1
MRCHKR: LDXI	12		;X 设为 12
IF1,<				;如果第一次扫描
MRCHR:	LDA	60000,X,>	;加载 60000,X
IF2,<				;如果第二次扫描
MRCHR:	LDA	SINCON+36,X,>	;加载 SINCON+36,X
	ANDI	77		;与 77
	STADY	POKER		;存储到 POKER,Y
	INY			;Y 加 1
	BNE	PKINC		;如果不为零，跳转到 PKINC
	INC	POKER+1		;POKER+1 加 1
PKINC:	DEX			;X 减 1
	BNE	MRCHR		;如果不为零，继续循环
	DEC	ANDMSK		;ANDMSK 减 1
	BNE	MRCHKR		;如果不为零，继续循环
	RTS			;返回
IF2,<PURGE ZSTORD>>		;如果第二次扫描，清除 ZSTORD
.CREF				;允许交叉引用
	LIST			;允许列表
FADD5:	JSR	SHIFTR		;DO A LONG SHIFT. ; 执行长移位
	BCC	FADD4		;CONTINUE WITH ADDITION. ; 继续加法
FADD:	JSR	CONUPK		;解包参数
FADDT:	JEQ	MOVFA		;IF FAC=0, RESULT IS IN ARG. ; 如果 FAC=0，结果在 ARG 中
	LDX	FACOV		;加载 FACOV
	STX	OLDOV		;存储到 OLDOV
	LDXI	ARGEXP		;DEFAULT IS SHIFT ARGUMENT. ; 默认移位参数
	LDA	ARGEXP		;IF ARG=0, FAC IS RESULT. ; 如果 ARG=0，FAC 是结果
FADDC:	TAY			;ALSO COPY ACCA INTO ACCY. ; 同时复制 ACCA 到 ACCY
	BEQ	ZERRTS		;RETURN. ; 返回
	SEC			;置位进位
	SBC	FACEXP		;减去 FACEXP
	BEQ	FADD4		;NO SHIFTING. ; 无需移位
	BCC	FADDA		;BR IF ARGEXP.LT.FACEXP. ; 如果 ARGEXP < FACEXP 则跳转
	STY	FACEXP		;RESULTING EXPONENT. ; 结果指数
	LDY	ARGSGN		;SINCE ARG IS BIGGER, IT'S ; 由于 ARG 更大，它的
	STY	FACSGN		;SIGN IS SIGN OF RESULT. ; 符号是结果的符号
	EORI	377		;SHIFT A NEGATIVE NUMBER OF PLACES. ; 移位负数位
	ADCI	0		;COMPLETE NEGATION. W/ C=1. ; 完成取反，C=1
	LDYI	0		;ZERO OLDOV. ; 清零 OLDOV
	STY	OLDOV		;存储到 OLDOV
	LDXI	FAC		;SHIFT THE FAC INSTEAD. ; 改为移位 FAC
	BNE	FADD1		;跳转到 FADD1
FADDA:	LDYI	0		;Y 清零
	STY	FACOV		;存储到 FACOV
FADD1:	CMPI	^D256-7		;FOR SPEED AND NECESSITY.  GETS ; 为了速度和必要性。获取
				;MOST LIKELY CASE TO SHIFTR FASTEST ; 最可能的情况以最快移位
				;AND ALLOWS SHIFTING OF NEG NUMS ; 并允许负数的移位
				;BY "QINT". ; 通过 "QINT"
	BMI	FADD5		;SHIFT BIG. ; 大移位
	TAY			;传输到 Y
	LDA	FACOV		;SET FACOV. ; 设置 FACOV
	LSR	1,X,		;GETS 0 IN MOST SIG BIT. ; 在最高位得到 0
	JSR	ROLSHF		;DO THE ROLLING. ; 执行滚动
FADD4:	BIT	ARISGN		;GET RESULTING SIGN. ; 获取结果符号
	BPL	FADD2		;IF POSITIVE, ADD. ; 如果为正，加法
				;CARRY IS CLEAR. ; 进位清除
FADD3:	LDYI	FACEXP		;Y 设为 FACEXP
	CPXI	ARGEXP		;FAC IS BIGGER. ; FAC 更大
	BEQ	SUBIT		;相等，跳转到 SUBIT
	LDYI	ARGEXP		;ARG IS BIGGER. ; ARG 更大
SUBIT:	SEC			;置位进位
	EORI	377		;按位取反
	ADC	OLDOV		;加 OLDOV
	STA	FACOV		;存储到 FACOV
	LDA	3+ADDPRC,Y	;加载 3+ADDPRC,Y
	SBC	3+ADDPRC,X	;减去 3+ADDPRC,X
	STA	FACLO		;存储到 FACLO
	LDA	2+ADDPRC,Y	;加载 2+ADDPRC,Y
	SBC	2+ADDPRC,X	;减去 2+ADDPRC,X
	STA	FACMO		;存储到 FACMO
IFN	ADDPRC,<		;如果定义了 ADDPRC
	LDA	2,Y		;加载 2,Y
	SBC	2,X		;减去 2,X
	STA	FACMOH>		;存储到 FACMOH
	LDA	1,Y		;加载 1,Y
	SBC	1,X		;减去 1,X
	STA	FACHO		;存储到 FACHO
FADFLT: BCS	NORMAL		;HERE IF SIGNS DIFFER. IF CARRY, ; 符号不同时到这里。如果进位，
				;FAC IS SET OK. ; FAC 设置正确
	JSR	NEGFAC		;NEGATE [FAC]. ; 对 [FAC] 取负
NORMAL: LDYI	0		;Y 清零
	TYA			;传输 Y 到 A
	CLC			;清进位
NORM3:	LDX	FACHO		;加载 FACHO
	BNE	NORM1		;如果不为零，跳转到 NORM1
	LDX	FACHO+1		;SHIFT 8 BITS AT A TIME FOR SPEED. ; 为了速度一次移位 8 位
	STX	FACHO		;存储到 FACHO
IFN	ADDPRC,<		;如果定义了 ADDPRC
	LDX	FACMOH+1	;加载 FACMOH+1
	STX	FACMOH>		;存储到 FACMOH
	LDX	FACMO+1		;加载 FACMO+1
	STX	FACMO		;存储到 FACMO
	LDX	FACOV		;加载 FACOV
	STX	FACLO		;存储到 FACLO
	STY	FACOV		;存储到 FACOV
	ADCI	10		;加 10
	CMPI	10*ADDPRC+30	;比较 10*ADDPRC+30
	BNE	NORM3		;不相等，继续循环
ZEROFC: LDAI	0		;NOT NEED BY NORMAL BUT BY OTHERS. ; 正常情况不需要，但其他情况需要
ZEROF1: STA	FACEXP		;NUMBER MUST BE ZERO. ; 数字必须为零
ZEROML: STA	FACSGN		;MAKE SIGN POSITIVE. ; 使符号为正
	RTS			;ALL DONE. ; 全部完成
FADD2:	ADC	OLDOV		;加 OLDOV
	STA	FACOV		;存储到 FACOV
	LDA	FACLO		;加载 FACLO
	ADC	ARGLO		;加 ARGLO
	STA	FACLO		;存储到 FACLO
	LDA	FACMO		;加载 FACMO
	ADC	ARGMO		;加 ARGMO
	STA	FACMO		;存储到 FACMO
IFN	ADDPRC,<		;如果定义了 ADDPRC
	LDA	FACMOH		;加载 FACMOH
	ADC	ARGMOH		;加 ARGMOH
	STA	FACMOH>		;存储到 FACMOH
	LDA	FACHO		;加载 FACHO
	ADC	ARGHO		;加 ARGHO
	STA	FACHO		;存储到 FACHO
	JMP	SQUEEZ		;GO ROUND IF SIGNS SAME. ; 如果符号相同，去循环

NORM2:	ADCI	1		;DECREMENT SHIFT COUNT. ; 递减移位计数
	ASL	FACOV		;SHIFT ALL LEFT ONE BIT. ; 全部左移一位
	ROL	FACLO		;循环左移 FACLO
	ROL	FACMO		;循环左移 FACMO
IFN	ADDPRC,<		;如果定义了 ADDPRC
	ROL	FACMOH>		;循环左移 FACMOH
	ROL	FACHO		;循环左移 FACHO
NORM1:	BPL	NORM2		;IF MSB=0 SHIFT AGAIN. ; 如果最高位=0，再次移位
	SEC			;置位进位
	SBC	FACEXP		;减去 FACEXP
	BCS	ZEROFC		;如果进位置位，跳转到 ZEROFC
	EORI	377		;按位取反
	ADCI	1		;COMPLEMENT. ; 取补
	STA	FACEXP		;存储到 FACEXP
SQUEEZ: BCC	RNDRTS		;BITS TO SHIFT? ; 有位移位？
RNDSHF: INC	FACEXP		;FACEXP 加 1
	BEQ	OVERR		;如果为零，跳转到 OVERR
	ROR	FACHO		;循环右移 FACHO
IFN	ADDPRC,<		;如果定义了 ADDPRC
	ROR	FACMOH>		;循环右移 FACMOH
	ROR	FACMO		;循环右移 FACMO
	ROR	FACLO		;循环右移 FACLO
	ROR	FACOV		;循环右移 FACOV
RNDRTS: RTS			;ALL DONE. ; 全部完成

NEGFAC: COM	FACSGN		;COMPLEMENT FAC	 ENTIRELY. ; 完全取反 FAC
NEGFCH: COM	FACHO		;COMPLEMENT JUST THE NUMBER. ; 仅取反数字
IFN	ADDPRC,<		;如果定义了 ADDPRC
	COM	FACMOH>		;取反 FACMOH
	COM	FACMO		;取反 FACMO
	COM	FACLO		;取反 FACLO
	COM	FACOV		;取反 FACOV
	INC	FACOV		;FACOV 加 1
	BNE	INCFRT		;如果不为零，跳转到 INCFRT
INCFAC: INC	FACLO		;FACLO 加 1
	BNE	INCFRT
	INC	FACMO
	BNE	INCFRT		;IF NO CARRY, RETURN. ; 若无进位，返回
IFN	ADDPRC,<		;如果定义了 ADDPRC
	INC	FACMOH		;FACMOH 加 1
	BNE	INCFRT>		;如果不为零，跳转到 INCFRT
	INC	FACHO		;CARRY INCREMENT. ; 进位增加
INCFRT: RTS			;返回

OVERR:	LDXI	ERROV		;加载 ERROV
	JMP	ERROR		;TELL USER. ; 告诉用户
;
; "SHIFTR" SHIFTS [X+1:X+3] [-ACCA]  BITS RIGHT. ; "SHIFTR" 将 [X+1:X+3] 右移 [-ACCA] 位
; SHIFTS BYTES TO START WITH IF POSSIBLE. ; 如果可能，先进行字节移位
;
MULSHF: LDXI	RESHO-1		;ENTRY POINT FOR MULTIPLIER. ; 乘法器的入口点
SHFTR2: LDY	3+ADDPRC,X,	;SHIFT BYTES FIRST. ; 先移位字节
	STY	FACOV
IFN	ADDPRC,<                 ; 如果定义了 ADDPRC
	LDY	3,X
	STY	4,X>
	LDY	2,X,		;GET MO. ; 获取 MO
	STY	3,X,		;STORE LO. ; 存储 LO
	LDY	1,X,		;GET HO. ; 获取 HO
	STY	2,X,		;STORE MO. ; 存储 MO
	LDY	BITS
	STY	1,X,		;STORE HO. ; 存储 HO
SHIFTR: ADCI	10
	BMI	SHFTR2
	BEQ	SHFTR2
	SBCI	10		;C CAN BE EITHER 1,0 AND IT WORKS. ; C 可以是 1 或 0，都能工作
	TAY
	LDA	FACOV
	BCS	SHFTRT		;EQUIV TO BEQ HERE. ; 此处等价于 BEQ
IFN	RORSW,<                 ; 如果定义了 RORSW
SHFTR3: ASL	1,X
	BCC	SHFTR4
	INC	1,X
SHFTR4: ROR	1,X
	ROR	1,X>		;YES, TWO OF THEM. ; 是的，两个 ROR
IFE	RORSW,<                 ; 如果未定义 RORSW
SHFTR3: PHA
	LDA	1,X
	ANDI	200
	LSR	1,X
	ORA	1,X
	STA	1,X
	SKIP1>
ROLSHF:
IFN	RORSW,<                 ; 如果定义了 RORSW
	ROR	2,X
	ROR	3,X
IFN	ADDPRC,<	ROR	4,X>	;ONE MO TIME. ; 再来一次
>
IFE	RORSW,<                 ; 如果未定义 RORSW
	PHA
	LDAI	0
	BCC	SHFTR5
	LDAI	200
SHFTR5: LSR	2,X
	ORA	2,X
	STA	2,X
	LDAI	0
	BCC	SHFTR6
	LDAI	200
SHFTR6: LSR	3,X
	ORA	3,X
	STA	3,X
IFN	ADDPRC,<                 ; 如果定义了 ADDPRC
	LDAI	0
	BCC	SHFT6A
	LDAI	200
SHFT6A: LSR	4,X
	ORA	4,X
	STA	4,X>>
IFN	RORSW,<ROR	A,>	;ROTATE ARGUMENT 1 BIT RIGHT. ; 参数右旋 1 位
IFE	RORSW,<                 ; 如果未定义 RORSW
	PLA
	PHP
	LSR	A,
	PLP
	BCC	SHFTR7
	ORAI	200>
SHFTR7: INY
	BNE	SHFTR3		;$$$ ( MOST EXPENSIVE ! ) ; $$$（最耗时的部分！）
SHFTRT: CLC			;CLEAR OUTPUT OF FACOV. ; 清除 FACOV 的输出
	RTS
PAGE
SUBTTL	NATURAL LOG FUNCTION. ; 子标题：自然对数函数
;
; CALCULATION IS BY: ; 计算方式：
; LN(F*2^N)=(N+LOG2(F))*LN(2)
; AN APPROXIMATION POLYNOMIAL IS USED TO CALCULATE LOG2(F). ; 使用近似多项式计算 LOG2(F)
;  CONSTANTS USED BY LOG: ; LOG 使用的常数
FONE:	201	; 1.0
	000
	000
	000
IFN	ADDPRC,<0>
IFE	ADDPRC,<
LOGCN2: 2	; DEGREE-1 ; 次数-1
	200	; 0.59897437
	031
	126
	142
	200	; 0.96147080
	166
	042
	363
	202	; 2.88539129
	070
	252
	100>

IFN	ADDPRC,<
LOGCN2: 3	;DEGREE-1 ; 次数-1
	177	;.43425594188
	136
	126
	313
	171
	200	; .57658454134
	023
	233
	013
	144
	200	; .96180075921
	166
	070
	223
	026
	202	; 2.8853900728
	070
	252
	073
	040>
SQRHLF: 200	; SQR(0.5) ; 0.5 的平方根
	065
	004
	363
IFN	ADDPRC,<064>
SQRTWO: 201	; SQR(2.0) ; 2.0 的平方根
	065
	004
	363
IFN	ADDPRC,<064>
NEGHLF: 200	; -1/2 ; 负二分之一
	200
	000
	000
IFN	ADDPRC,<0>
LOG2:	200	; LN(2) ; 2 的自然对数
	061
	162
IFE	ADDPRC,<030>
IFN	ADDPRC,<027
	370>

LOG:	JSR	SIGN		;IS IT POSITIVE? ; 是正数吗？
	BEQ	LOGERR
	BPL	LOG1
LOGERR: JMP	FCERR		;CAN'T TOLERATE NEG OR ZERO. ; 不能接受负数或零
LOG1:	LDA	FACEXP		;GET EXPONENT INTO ACCA. ; 将指数获取到 ACCA
	SBCI	177		;REMOVE BIAS. (CARRY IS OFF) ; 移除偏置（进位已清除）
	PHA			;SAVE AWHILE. ; 暂时保存
	LDAI	200
	STA	FACEXP		;RESULT IS FAC IN RANGE [0.5,1]. ; 结果 FAC 在范围 [0.5,1] 内
	LDWDI	SQRHLF		;GET POINTER TO SQR(0.5). ; 获取指向 SQR(0.5) 的指针

; CALCULATE (F-SQR(.5))/(F+SQR(.5)) ; 计算 (F-SQR(.5))/(F+SQR(.5))

	JSR	FADD		;ADD TO FAC. ; 加到 FAC
	LDWDI	SQRTWO		;GET SQR(2.). ; 获取 SQR(2.)
	JSR	FDIV
	LDWDI	FONE
	JSR	FSUB
	LDWDI	LOGCN2
	JSR	POLYX		;EVALUATE APPROXIMATION POLYNOMIAL. ; 求值近似多项式
	LDWDI	NEGHLF		;ADD IN LAST CONSTANT. ; 加上最后一个常数
	JSR	FADD
	PLA			;GET EXPONENT BACK. ; 取回指数
	JSR	FINLOG		;ADD IT IN. ; 加上它
MULLN2: LDWDI	LOG2		;MULTIPLY RESULT BY LOG(2.0). ; 结果乘以 LOG(2.0)
;	JMP	FMULT		;MULTIPLY TOGETHER. ; 相乘
PAGE
SUBTTL	FLOATING MULTIPLICATION AND DIVISION. ; 子标题：浮点乘法和除法
	;MULTIPLICATION		FAC:=ARG*FAC. ; 乘法 FAC:=ARG*FAC
FMULT:	JSR	CONUPK		;UNPACK THE CONSTANT INTO ARG FOR USE. ; 将常数解包到 ARG 以供使用
FMULTT: JEQ	MULTRT		;IF FAC=0, RETURN. FAC IS SET. ; 如果 FAC=0，返回。FAC 已设置
	JSR	MULDIV		;FIX UP THE EXPONENTS. ; 调整指数
	LDAI	0		;TO CLEAR RESULT. ; 清零结果
	STA	RESHO
IFN	ADDPRC,<                 ; 如果定义了 ADDPRC
	STA	RESMOH>
	STA	RESMO
	STA	RESLO
	LDA	FACOV
	JSR	MLTPLY
	LDA	FACLO		;MLTPLY ARG BY FACLO. ; ARG 乘以 FACLO
	JSR	MLTPLY
	LDA	FACMO		;MLTPLY ARG BY FACMO. ; ARG 乘以 FACMO
	JSR	MLTPLY
IFN	ADDPRC,<                 ; 如果定义了 ADDPRC
	LDA	FACMOH
	JSR	MLTPLY>
	LDA	FACHO		;MLTPLY ARG BY FACHO. ; ARG 乘以 FACHO
	JSR	MLTPL1
	JMP	MOVFR		;MOVE RESULT INTO FAC, ; 将结果移入 FAC
				;NORMALIZE RESULT, AND RETURN. ; 规范化结果并返回
MLTPLY: JEQ	MULSHF		;SHIFT RESULT RIGHT 1 BYTE. ; 结果右移 1 字节
MLTPL1: LSR	A,
	ORAI	200
MLTPL2: TAY
	BCC	MLTPL3		;IT MULT BIT=0, JUST SHIFT. ; 乘位=0，仅移位
	CLC
	LDA	RESLO
	ADC	ARGLO
	STA	RESLO
	LDA	RESMO
	ADC	ARGMO
	STA	RESMO
IFN	ADDPRC,<                 ; 如果定义了 ADDPRC
	LDA	RESMOH
	ADC	ARGMOH
	STA	RESMOH>
	LDA	RESHO
	ADC	ARGHO
	STA	RESHO
MLTPL3: ROR	RESHO
IFN	ADDPRC,<                 ; 如果定义了 ADDPRC
	ROR	RESMOH>
	ROR	RESMO
	ROR	RESLO
	ROR	FACOV		;SAVE FOR ROUNDING. ; 保存用于舍入
	TYA
	LSR	A,		;CLEAR MSB SO WE GET A CLOSER TO 0. ; 清除 MSB 以便更接近 0
	BNE	MLTPL2		;SLOW AS A TURTLE ! ; 慢如乌龟！
MULTRT: RTS

	;ROUTINE TO UNPACK MEMORY INTO ARG. ; 将内存解包到 ARG 的例程
CONUPK: STWD	INDEX1
	LDYI	3+ADDPRC
	LDADY	INDEX1
	STA	ARGLO
	DEY
	LDADY	INDEX1
	STA	ARGMO
	DEY
IFN	ADDPRC,<                 ; 如果定义了 ADDPRC
	LDADY	INDEX1
	STA	ARGMOH
	DEY>
	LDADY	INDEX1
	STA	ARGSGN
	EOR	FACSGN
	STA	ARISGN
	LDA	ARGSGN
	ORAI	200
	STA	ARGHO
	DEY
	LDADY	INDEX1
	STA	ARGEXP
	LDA	FACEXP		;SET CODES OF FACEXP. ; 设置 FACEXP 的状态
	RTS

	;CHECK SPECIAL CASES AND ADD EXPONENTS FOR FMULT, FDIV. ; 检查特殊情况并为 FMULT、FDIV 添加指数
MULDIV: LDA	ARGEXP		;EXP OF ARG=0? ; ARG 的指数=0？
MLDEXP: BEQ	ZEREMV		;SO WE GET ZERO EXPONENT. ; 因此我们得到零指数
	CLC
	ADC	FACEXP		;RESULT IS IN ACCA. ; 结果在 ACCA 中
	BCC	TRYOFF		;FIND [C] XOR [N]. ; 找到 [C] 异或 [N]
	BMI	GOOVER		;OVERFLOW IF BITS MATCH. ; 如果位匹配则溢出
	CLC
	SKIP2
TRYOFF: BPL	ZEREMV		;UNDERFLOW. ; 下溢
	ADCI	200		;ADD BIAS. ; 添加偏置
	STA	FACEXP
	JEQ	ZEROML		;ZERO THE REST OF IT. ; 其余部分清零
	LDA	ARISGN
	STA	FACSGN		;ARISGN IS RESULT'S SIGN. ; ARISGN 是结果的符号
	RTS			;DONE. ; 完成
MLDVEX: LDA	FACSGN		;GET SIGN. ; 获取符号
	EORI	377		;COMPLEMENT IT. ; 取反
	BMI	GOOVER
ZEREMV: PLA			;GET ADDR OFF STACK. ; 从堆栈中获取地址
	PLA	
	JMP	ZEROFC		;UNDERFLOW. ; 下溢
GOOVER: JMP	OVERR		;OVERFLOW. ; 溢出

	;MULTIPLY FAC BY 10. ; FAC 乘以 10
MUL10:	JSR	MOVAF		;COPY FAC INTO ARG. ; 将 FAC 复制到 ARG
	TAX
	BEQ	MUL10R		;IF [FAC]=0, GOT ANSWER. ; 如果 [FAC]=0，得到答案
	CLC
	ADCI	2		;AUGMENT EXP BY 2. ; 指数增加 2
	BCS	GOOVER		;OVERFLOW. ; 溢出
FINML6: LDXI	0
	STX	ARISGN		;SIGNS ARE SAME. ; 符号相同
	JSR	FADDC		;ADD TOGETHER. ; 相加
	INC	FACEXP		;MULTIPLY BY TWO. ; 乘以二
	BEQ	GOOVER		;OVERFLOW. ; 溢出
MUL10R: RTS

	; DIVIDE FAC BY 10. ; FAC 除以 10
TENZC:	204
	040
	000
	000
IFN	ADDPRC,<0>
DIV10:	JSR	MOVAF		;MOVE FAC TO ARG. ; 将 FAC 移动到 ARG
	LDWDI	TENZC		;POINT TO CONSTANT OF 10.0 ; 指向常数 10.0
	LDXI	0		;SIGNS ARE BOTH POSITIVE. ; 符号均为正
FDIVF:	STX	ARISGN
	JSR	MOVFM		;PUT IT INTO FAC. ; 放入 FAC
	JMP	FDIVT		;SKIP OVER NEXT TWO BYTES. ; 跳过接下来的两个字节
FDIV:	JSR	CONUPK		;UNPACK CONSTANT. ; 解包常数
FDIVT:	BEQ	DV0ERR		;CAN'T DIVIDE BY ZERO ! ; 不能除以零！
				;(NOT ENOUGH ROOM TO STORE RESULT.) ; （没有足够空间存储结果）
	JSR	ROUND		;TAKE FACOV INTO ACCT IN FAC. ; 在 FAC 中考虑 FACOV
	LDAI	0		;NEGATE FACEXP. ; 对 FACEXP 取负
	SEC
	SBC	FACEXP
	STA	FACEXP
	JSR	MULDIV		;FIX UP EXPONENTS. ; 调整指数
	INC	FACEXP		;SCALE IT RIGHT. ; 正确缩放
	BEQ	GOOVER		;OVERFLOW. ; 溢出
	LDXI	^D256-3-ADDPRC	;SETUP PROCEDURE. ; 设置过程
	LDAI	1
DIVIDE:				;THIS IS THE BEST CODE IN THE WHOLE PILE. ; 这是整个代码中最棒的部分
	LDY	ARGHO		;SEE WHAT RELATION HOLDS. ; 查看保持的关系
	CPY	FACHO
	BNE	SAVQUO		;[C]=0,1. N(C=0)=0. ; [C]=0,1。N(C=0)=0
IFN	ADDPRC,<                 ; 如果定义了 ADDPRC
	LDY	ARGMOH
	CPY	FACMOH
	BNE	SAVQUO>
	LDY	ARGMO
	CPY	FACMO
	BNE	SAVQUO
	LDY	ARGLO
	CPY	FACLO
SAVQUO: PHP
	ROL	A,		;SAVE RESULT. ; 保存结果
	BCC	QSHFT		;IF NOT DONE, CONTINUE. ; 如果未完成，继续
	INX
	STA	RESLO,X
	BEQ	LD100
	BPL	DIVNRM		;NOTE THIS REQ 1 MO RAM THEN NECESS. ; 注意这需要 1 字节 RAM，然后是必需的
	LDAI	1
QSHFT:	PLP			;RETURN CONDITION CODES. ; 恢复条件码
	BCS	DIVSUB		;FAC .LE. ARG. ; FAC ≤ ARG
SHFARG: ASL	ARGLO		;SHIFT ARG ONE PLACE LEFT. ; ARG 左移一位
	ROL	ARGMO
IFN	ADDPRC,<                 ; 如果定义了 ADDPRC
	ROL	ARGMOH>
	ROL	ARGHO
	BCS	SAVQUO		;SAVE A RESULT OF ONE FOR THIS POSITION ; 为此位置保存结果 1
				;AND DIVIDE. ; 并除法
	BMI	DIVIDE		;IF MSB ON, GO DECIDE WHETHER TO SUB. ; 如果 MSB 开启，去决定是否减法
	BPL	SAVQUO
DIVSUB: TAY			;NOTICE C MUST BE ON HERE. ; 注意此处 C 必须为开
	LDA	ARGLO
	SBC	FACLO
	STA	ARGLO
	LDA	ARGMO
	SBC	FACMO
	STA	ARGMO
IFN	ADDPRC,<                 ; 如果定义了 ADDPRC
	LDA	ARGMOH
	SBC	FACMOH
	STA	ARGMOH>
	LDA	ARGHO
	SBC	FACHO
	STA	ARGHO
	TYA
	JMP	SHFARG
LD100:	LDAI	100		;ONLY WANT TWO MORE BITS. ; 只需要另外两位
	BNE	QSHFT		;ALWAYS BRANCHES. ; 总是分支
DIVNRM: REPEAT	6,<ASL	A>	;GET LAST TWO BITS INTO MSB AND B6. ; 将最后两位获取到 MSB 和 B6
	STA	FACOV
	PLP			;TO GET GARBAGE OFF STACK. ; 从堆栈中清除垃圾
	JMP	MOVFR		;MOVE RESULT INTO FAC, THEN ; 将结果移入 FAC，然后
				;NORMALIZE RESULT AND RETURN. ; 规范化结果并返回
DV0ERR: LDXI	ERRDV0
	JMP	ERROR
PAGE
SUBTTL	FLOATING POINT MOVEMENT ROUTINES. ; 子标题：浮点移动例程
	;MOVE RESULT TO FAC. ; 将结果移动到 FAC
MOVFR:	LDA	RESHO
	STA	FACHO
IFN	ADDPRC,<                 ; 如果定义了 ADDPRC
	LDA	RESMOH
	STA	FACMOH>
	LDA	RESMO
	STA	FACMO
	LDA	RESLO		;MOVE LO AND SGN. ; 移动 LO 和 SGN
	STA	FACLO
	JMP	NORMAL		;ALL DONE. ; 全部完成

	;MOVE MEMORY INTO FAC (UNPACKED). ; 将内存移动到 FAC（未打包）
MOVFM:	STWD	INDEX1
	LDYI	3+ADDPRC
	LDADY	INDEX1
	STA	FACLO
	DEY
	LDADY	INDEX1
	STA	FACMO
	DEY
IFN	ADDPRC,<                 ; 如果定义了 ADDPRC
	LDADY	INDEX1
	STA	FACMOH
	DEY>
	LDADY	INDEX1
	STA	FACSGN
	ORAI	200
	STA	FACHO
	DEY
	LDADY	INDEX1
	STA	FACEXP		;LEAVE SWITCHES SET ON EXP. ; 保持开关设置在 EXP 上
	STY	FACOV
	RTS

	;MOVE NUMBER FROM FAC TO MEMORY. ; 将数字从 FAC 移动到内存
MOV2F:	LDXI	TEMPF2
	SKIP2
MOV1F:	LDXI	TEMPF1
MOVML:	LDYI	0
	BEQ	MOVMF		;ALWAYS BRANCHES. ; 总是分支
MOVVF:	LDXY	FORPNT
MOVMF:	JSR	ROUND
	STXY	INDEX1
	LDYI	3+ADDPRC
	LDA	FACLO
	STADY	INDEX
	DEY
	LDA	FACMO
	STADY	INDEX
	DEY
IFN	ADDPRC,<                 ; 如果定义了 ADDPRC
	LDA	FACMOH
	STADY	INDEX
	DEY>
	LDA	FACSGN		;INCLUDE SIGN IN HO. ; 在 HO 中包含符号
	ORAI	177
	AND	FACHO
	STADY	INDEX
	DEY
	LDA	FACEXP
	STADY	INDEX
	STY	FACOV		;ZERO IT SINCE ROUNDED. ; 由于已舍入，将其清零
	RTS			;[Y]=0.

	;MOVE ARG INTO FAC. ; 将 ARG 移动到 FAC
MOVFA:	LDA	ARGSGN
MOVFA1: STA	FACSGN
	LDXI	4+ADDPRC
MOVFAL: LDA	ARGEXP-1,X
	STA	FACEXP-1,X
	DEX
	BNE	MOVFAL
	STX	FACOV
	RTS

	;MOVE FAC INTO ARG. ; 将 FAC 移动到 ARG
MOVAF:	JSR	ROUND
MOVEF:	LDXI	5+ADDPRC
MOVAFL: LDA	FACEXP-1,X
	STA	ARGEXP-1,X
	DEX
	BNE	MOVAFL
	STX	FACOV		;ZERO IT SINCE ROUNDED. ; 由于已舍入，将其清零
MOVRTS: RTS

ROUND:	LDA	FACEXP		;ZERO? ; 为零？
	BEQ	MOVRTS		;YES. DONE ROUNDING. ; 是。舍入完成
	ASL	FACOV		;ROUND? ; 舍入？
	BCC	MOVRTS		;NO. MSB OFF. ; 否。MSB 关闭
INCRND: JSR	INCFAC		;YES, ADD ONE TO LSB(FAC). ; 是，向 LSB(FAC) 加一
	BNE	MOVRTS		;NO CARRY MEANS DONE. ; 无进位表示完成
	JMP	RNDSHF		;SQUEEZ MSB IN AND RTS. ; 挤入 MSB 并返回
				;NOTE [C]=1 SINCE INCFAC DOESNT TOUCH C. ; 注意 [C]=1，因为 INCFAC 不接触 C
PAGE
SUBTTL	SIGN, SGN, FLOAT, NEG, ABS. ; 子标题：SIGN、SGN、FLOAT、NEG、ABS

	;PUT SIGN OF FAC IN ACCA. ; 将 FAC 的符号放入 ACCA
SIGN:	LDA	FACEXP
	BEQ	SIGNRT		;IF NUMBER IS ZERO, SO IS RESULT. ; 如果数字为零，结果也为零
FCSIGN: LDA	FACSGN
FCOMPS: ROL	A
	LDAI	^O377		;ASSUME NEGATIVE. ; 假设为负
	BCS	SIGNRT
	LDAI	1		;GET +1. ; 获取 +1
SIGNRT: RTS

	;SGN FUNCTION. ; SGN 函数
SGN:	JSR	SIGN

	;FLOAT THE SIGNED INTEGER IN ACCA. ; 将 ACCA 中的有符号整数浮点化
FLOAT:	STA	FACHO		;PUT [ACCA] IN HIGH ORDER. ; 将 [ACCA] 放入高位
	LDAI	0
	STA	FACHO+1
	LDXI	210		;GET THE EXPONENT. ; 获取指数

	;FLOAT THE SIGNED NUMBER IN FAC. ; 将 FAC 中的有符号数浮点化
FLOATS: LDA	FACHO
	EORI	377
	ROL	A,		;GET COMP OF SIGN IN CARRY. ; 获取符号的补码存入进位
FLOATC: LDAI	0		;ZERO [ACCA] BUT NOT CARRY. ; 清零 [ACCA] 但不清除进位
	STA	FACLO
IFN	ADDPRC,<                 ; 如果定义了 ADDPRC
	STA	FACMO>
FLOATB: STX	FACEXP
	STA	FACOV
	STA	FACSGN
	JMP	FADFLT

	;ABSOLUTE VALUE OF FAC. ; FAC 的绝对值
ABS:	LSR	FACSGN
	RTS

PAGE
SUBTTL	COMPARE TWO NUMBERS. ; 子标题：比较两个数字
	;A=1 IF ARG .LT. FAC. ;如果 ARG < FAC，则 A=1
	;A=0 IF ARG=FAC. ;如果 ARG=FAC，则 A=0
	;A=-1 IF ARG .GT. FAC. ;如果 ARG > FAC，则 A=-1
FCOMP:	STA	INDEX2
FCOMPN: STY	INDEX2+1
	LDYI	0
	LDADY	INDEX2		;HAS ARGEXP. ; 具有 ARGEXP
	INY			;BUMP PNTR UP. ; 指针增加
	TAX			;SAVE A IN X AND RESET CODES. ; 将 A 保存在 X 中并重置代码
	BEQ	SIGN
	LDADY	INDEX2
	EOR	FACSGN		;SIGNS THE SAME. ; 符号相同
	BMI	FCSIGN		;SIGNS DIFFER SO RESULT IS ; 符号不同，因此结果是
				;SIGN OF FAC AGAIN. ; 再次是 FAC 的符号
FOUTCP: CPX	FACEXP
	BNE	FCOMPC
	LDADY	INDEX2
	ORAI	200
	CMP	FACHO
	BNE	FCOMPC
	INY
IFN	ADDPRC,<                 ; 如果定义了 ADDPRC
	LDADY	INDEX2
	CMP	FACMOH
	BNE	FCOMPC
	INY>
	LDADY	INDEX2
	CMP	FACMO
	BNE	FCOMPC
	INY
	LDAI	177
	CMP	FACOV
	LDADY	INDEX2
	SBC	FACLO		;GET ZERO IF EQUAL. ; 如果相等则得到零
	BEQ	QINTRT
FCOMPC: LDA	FACSGN
	BCC	FCOMPD
	EORI	377
FCOMPD: JMP	FCOMPS		;A PART OF SIGN SETS ACCA UP. ; SIGN 的一部分设置 ACCA

PAGE
SUBTTL	GREATEST INTEGER FUNCTION. ; 子标题：最大整数函数
	;QUICK GREATEST INTEGER FUNCTION. ;快速最大整数函数
	;LEAVES INT(FAC) IN FACHO&MO&LO SIGNED. ;将 INT(FAC) 留在 FACHO&MO&LO 中（有符号）
	;ASSUMES FAC .LT. 2^23 = 8388608 ;假设 FAC < 2^23 = 8388608
QINT:	LDA	FACEXP
	BEQ	CLRFAC		;IF ZERO, GOT IT. ; 如果为零，得到它
	SEC
	SBCI	8*ADDPRC+230	;GET NUMBER OF PLACES TO SHIFT. ; 获取要移位的位数
	BIT	FACSGN
	BPL	QISHFT
	TAX
	LDAI	377
	STA	BITS		;PUT 377 IN WHEN SHFTR SHIFTS BYTES. ; 当 SHFTR 移位字节时放入 377
	JSR	NEGFCH		;TRULY NEGATE QUANTITY IN FAC. ; 真正对 FAC 中的量取负
	TXA
QISHFT: LDXI	FAC
	CMPI	^D256-7
	BPL	QINT1		;IF NUMBER OF PLACES .GE. 7 ; 如果位数 ≥ 7
				;SHIFT 1 PLACE AT A TIME. ; 每次移位 1 位
	JSR	SHIFTR		;START SHIFTING BYTES, THEN BITS. ; 开始移位字节，然后位
	STY	BITS		;ZERO BITS SINCE ADDER WANTS ZERO. ; 清零位，因为加法器需要零
QINTRT: RTS
QINT1:	TAY			;PUT COUNT IN COUNTER. ; 将计数放入计数器
	LDA	FACSGN
	ANDI	200		;GET SIGN BIT. ; 获取符号位
	LSR	FACHO		;SAVE FIRST SHIFTED BYTE. ; 保存第一个移位后的字节
	ORA	FACHO
	STA	FACHO
	JSR	ROLSHF		;SHIFT THE REST. ; 移位其余部分
	STY	BITS		;ZERO [BITS]. ; 清零 [BITS]
	RTS

	;GREATEST INTEGER FUNCTION. ; 最大整数函数
INT:	LDA	FACEXP
	CMPI	8*ADDPRC+230
	BCS	INTRTS		;FORGET IT. ; 忽略它
	JSR	QINT
	STY	FACOV		;CLR OVERFLOW BYTE. ; 清除溢出字节
	LDA	FACSGN
	STY	FACSGN		;MAKE FAC LOOK POSITIVE. ; 使 FAC 看起来为正
	EORI	200		;GET COMPLEMENT OF SIGN IN CARRY. ; 获取符号的补码存入进位
	ROL	A,
	LDAI	8*ADDPRC+230
	STA	FACEXP
	LDA	FACLO
	STA	INTEGR
	JMP	FADFLT
CLRFAC: STA	FACHO		;MAKE IT REALLY ZERO. ; 使其真正为零
IFN	ADDPRC,<STA FACMOH>
	STA	FACMO
	STA	FACLO
	TAY
INTRTS: RTS
PAGE
SUBTTL	FLOATING POINT INPUT ROUTINE. ; 子标题：浮点输入例程
	;NUMBER INPUT IS LEFT IN FAC. ;数字输入留在 FAC 中
	;AT ENTRY [TXTPTR] POINTS TO THE FIRST CHARACTER IN A TEXT BUFFER. ;入口处 [TXTPTR] 指向文本缓冲区中的第一个字符
	;THE FIRST CHARACTER IS ALSO IN ACCA. FIN PACKS THE DIGITS ;第一个字符也在 ACCA 中。FIN 将数字打包到 FAC 中作为整数，并跟踪小数点位置
	;INTO THE FAC AS AN INTEGER AND KEEPS TRACK OF WHERE THE
	;DECIMAL POINT IS. [DPTFLG] TELL WHETHER A DP HAS BEEN ;[DPTFLG] 告知是否已看到小数点
	;SEEN. [DECCNT] IS THE NUMBER OF DIGITS AFTER THE DP. ;[DECCNT] 是小数点后的位数
	;AT THE END [DECCNT] AND THE EXPONENT ARE USED TO ;最后使用 [DECCNT] 和指数来确定乘以或除以十的次数以获得正确的数字
	;DETERMINE HOW MANY TIMES TO MULTIPLY OR DIVIDE BY TEN
	;TO GET THE CORRECT NUMBER.
FIN:	LDYI	0		;ZERO FACSGN&SGNFLG. ; 清零 FACSGN 和 SGNFLG
	LDXI	11+ADDPRC	;ZERO EXP AND HO (AND MOH). ; 清零 EXP 和 HO（以及 MOH）
FINZLP: STY	DECCNT,X	;ZERO MO AND LO. ; 清零 MO 和 LO
	DEX			;ZERO TENEXP AND EXPSGN ; 清零 TENEXP 和 EXPSGN
	BPL	FINZLP		;ZERO DECCNT, DPTFLG. ; 清零 DECCNT、DPTFLG
	BCC	FINDGQ		;FLAGS STILL SET FROM CHRGET. ; 标志仍由 CHRGET 设置
	CMPI	"-"		;A NEGATIVE SIGN? ; 负号？
	BNE	QPLUS		;NO, TRY PLUS SIGN. ; 否，尝试正号
	STX	SGNFLG		;IT'S NEGATIVE. (X=377). ; 它是负数（X=377）
	BEQ	FINC		;ALWAYS BRANCHES. ; 总是分支
QPLUS:	CMPI	"+"		;PLUS SIGN? ; 正号？
	BNE	FIN1		;YES, SKIP IT. ; 是，跳过它
FINC:	JSR	CHRGET
FINDGQ: BCC	FINDIG
FIN1:	CMPI	"."		;THE DP? ; 小数点？
	BEQ	FINDP		;NO KIDDING. ; 没错
	CMPI	"E"		;EXPONENT FOLLOWS. ; 后面是指数
	BNE	FINE		;NO. ; 否
	;HERE TO CHECK FOR SIGN OF EXP. ; 此处检查指数的符号
	JSR	CHRGET		;YES. GET ANOTHER. ; 是。获取另一个
	BCC	FNEDG1		;IT IS A DIGIT. (EASIER THAN ; 是数字（比
				;BACKING UP POINTER.) ; 回退指针更容易）
	CMPI	MINUTK		;MINUS? ; 减号？
	BEQ	FINEC1		;NEGATE. ; 取负
	CMPI	"-"		;MINUS SIGN? ; 减号？
	BEQ	FINEC1
	CMPI	PLUSTK		;PLUS? ; 加号？
	BEQ	FINEC
	CMPI	"+"		;PLUS SIGN? ; 加号？
	BEQ	FINEC
	BNE	FINEC2
FINEC1: ROR	EXPSGN		;TURN IT ON. ; 开启它
FINEC:	JSR	CHRGET		;GET ANOTHER. ; 获取另一个
FNEDG1: BCC	FINEDG		;IT IS A DIGIT. ; 是数字
FINEC2: BIT	EXPSGN
	BPL	FINE
	LDAI	0
	SEC
	SBC	TENEXP
	JMP	FINE1
FINDP:	ROR	DPTFLG
	BIT	DPTFLG
	BVC	FINC
FINE:	LDA	TENEXP
FINE1:	SEC
	SBC	DECCNT		;GET NUMBER OF PLACES TO SHIFT. ; 获取要移位的位数
	STA	TENEXP
	BEQ	FINQNG		;NEGATE? ; 取负？
	BPL	FINMUL		;POSITIVE SO MULTIPLY. ; 正数所以乘法
FINDIV: JSR	DIV10
	INC	TENEXP		;DONE? ; 完成？
	BNE	FINDIV		;NO. ; 否
	BEQ	FINQNG		;YES. ; 是
FINMUL: JSR	MUL10
	DEC	TENEXP		;DONE? ; 完成？
	BNE	FINMUL		;NO ; 否
FINQNG: LDA	SGNFLG
	BMI	NEGXQS		;IF POSITIVE, RETURN. ; 如果为正，返回
	RTS
NEGXQS: JMP	NEGOP		;OTHERWISE, NEGATE AND RETURN. ; 否则，取负并返回

FINDIG: PHA
	BIT	DPTFLG
	BPL	FINDG1
	INC	DECCNT
FINDG1: JSR	MUL10
	PLA			;GET IT BACK. ; 取回它
	SEC
	SBCI	"0"
	JSR	FINLOG		;ADD IT IN. ; 加入它
	JMP	FINC

FINLOG: PHA
	JSR	MOVAF		;SAVE FAC FOR LATER. ; 保存 FAC 供后续使用
	PLA
	JSR	FLOAT		;FLOAT THE VALUE IN ACCA. ; 将 ACCA 中的值浮点化
	LDA	ARGSGN
	EOR	FACSGN
	STA	ARISGN		;RESULTANT SIGN. ; 结果符号
	LDX	FACEXP		;SET SIGNS ON THING TO ADD. ; 设置要添加的内容的符号
	JMP	FADDT		;ADD TOGETHER AND RETURN. ; 相加并返回

	;HERE PACK IN THE NEXT DIGIT OF THE EXPONENT. ;此处打包指数的下一位数字
	;MULTIPLY THE OLD EXP BY 10 AND ADD IN THE NEXT ;将旧指数乘以 10 并加入下一位数字
	;DIGIT. NOTE: EXP OVERFLOW IS NOT CHECKED FOR. ;注意：不检查指数溢出
FINEDG: LDA	TENEXP		;GET EXP SO FAR. ; 获取目前的指数
	CMPI	12		;WILL RESULT BE .GE. 100? ; 结果会 ≥ 100 吗？
	BCC	MLEX10	
	LDAI	144		;GET 100. ; 获取 100
	BIT	EXPSGN
	BMI	MLEXMI		;IF NEG EXP, NO CHK FOR OVERR. ; 如果负指数，不检查溢出
	JMP	OVERR
MLEX10: ASL	A,		;MULT BY 2 TWICE ; 乘以 2 两次
	ASL	A
	CLC			;POSSIBLE SHIFT OUT OF HIGH. ; 可能移出高位
	ADC	TENEXP		;LIKE MULTIPLYING BY FIVE. ; 如同乘以五
	ASL	A,		;AND NOW BY TEN. ; 现在乘以十
	CLC
	LDYI	0
	ADCDY	TXTPTR
	SEC
	SBCI	"0"
MLEXMI: STA	TENEXP		;SAVE RESULT. ; 保存结果
	JMP	FINEC
PAGE
SUBTTL	FLOATING POINT OUTPUT ROUTINE. ; 子标题：浮点输出例程

IFE	ADDPRC,<
NZ0999: 221	; 99999.9499
	103
	117
	370
NZ9999: 224	; 999999.499
	164
	043
	367
NZMIL:	224	; 10^6. ; 10^6
	164
	044
	000>
IFN	ADDPRC,<
NZ0999: 233	; 99999999.9499
	076
	274
	037
	375
NZ9999: 236	; 999999999.499
	156
	153
	047
	375
NZMIL:	236	; 10^9 ; 10^9
	156
	153
	050
	000>
	;ENTRY TO LINPRT. ; LINPRT 的入口
INPRT:	LDWDI	INTXT
	JSR	STROU2
	LDA	CURLIN+1
	LDX	CURLIN
LINPRT: STWX	FACHO
	LDXI	220		;EXPONENT OF 16. ; 16 的指数
	SEC			;NUMBER IS POSITIVE. ; 数字为正
	JSR	FLOATC
	JSR	FOUT
STROU2: JMP	STROUT		;PRINT AND RETURN. ; 打印并返回

FOUT:	LDYI	1
FOUTC:	LDAI	" "		;PRINT SPACE IF POSITIVE. ; 如果为正，打印空格
	BIT	FACSGN
	BPL	FOUT1
	LDAI	"-"
FOUT1:	STA	FBUFFR-1,Y,	;STORE THE CHARACTER. ; 存储字符
	STA	FACSGN		;MAKE FAC POS FOR QINT. ; 为使 QINT 将 FAC 置为正
	STY	FBUFPT		;SAVE FOR LATER. ; 保存供后续使用
	INY
	LDAI	"0"		;GET ZERO TO TYPE IF FAC=0. ; 如果 FAC=0，获取零以打印
	LDX	FACEXP
	JEQ	FOUT19
	LDAI	 0
	CPXI	200		;IS NUMBER .LT. 1.0 ? ; 数字 < 1.0 吗？
	BEQ	FOUT37		;NO. ; 否
	BCS	FOUT7
FOUT37: LDWDI	NZMIL		;MULTIPLY BY 10^6. ; 乘以 10^6
	JSR	FMULT
	LDAI	^D256-3*ADDPRC-6
FOUT7:	STA	DECCNT		;SAVE COUNT OR ZERO IT. ; 保存计数或清零
FOUT4:	LDWDI	NZ9999
	JSR	FCOMP		;IS NUMBER .GT. 999999.499 ? ; 数字 > 999999.499 吗？
				;OR 999999999.499? ; 或 999999999.499？
	BEQ	BIGGES
	BPL	FOUT9		;YES. MAKE IT SMALLER. ; 是。使其更小
FOUT3:	LDWDI	NZ0999
	JSR	FCOMP		;IS NUMBER .GT. 99999.9499 ? ; 数字 > 99999.9499 吗？
				; OR 99999999.9499? ; 或 99999999.9499？
	BEQ	FOUT38
	BPL	FOUT5		;YES. DONE MULTIPLYING. ; 是。乘法完成
FOUT38: JSR	MUL10		;MAKE IT BIGGER. ; 使其更大
	DEC	DECCNT
	BNE	FOUT3		;SEE IF THAT DOES IT. ; 查看是否有效
				;THIS ALWAYS GOES. ; 总是执行
FOUT9:	JSR	DIV10		;MAKE IT SMALLER. ; 使其更小
	INC	DECCNT
	BNE	FOUT4		;SEE IF THAT DOES IT. ; 查看是否有效
				;THIS ALWAYS GOES. ; 总是执行

FOUT5:	JSR	FADDH		;ADD A HALF TO ROUND UP. ; 加二分之一以向上舍入
BIGGES: JSR	QINT
	LDXI	1		;DECIMAL POINT COUNT. ; 小数点计数
	LDA	DECCNT
	CLC
	ADCI	3*ADDPRC+7	;SHOULD NUMBER BE PRINTED IN E NOTATION? ; 数字应以 E 表示法打印吗？
				;IE, IS NUMBER .LT. .01 ? ; 即，数字 < .01 吗？
	BMI	FOUTPI		;YES. ; 是
	CMPI	3*ADDPRC+10	;IS IT .GT. 999999 (999999999)? ; 它 > 999999 (999999999) 吗？
	BCS	FOUT6		;YES. USE E NOTATION. ; 是。使用 E 表示法
	ADCI	^O377		;NUMBER OF PLACES BEFORE DECIMAL POINT. ; 小数点前的位数
	TAX			;PUT INTO ACCX. ; 放入 ACCX
	LDAI	2		;NO E NOTATION. ; 无 E 表示法
FOUTPI: SEC
FOUT6:	SBCI	2		;EFFECTIVELY ADD 5 TO ORIG EXP. ; 实际上向原始指数加 5
	STA	TENEXP		;THAT IS THE EXPONENT TO PRINT. ; 那是要打印的指数
	STX	DECCNT		;NUMBER OF DECIMAL PLACES. ; 小数位数
	TXA
	BEQ	FOUT39
	BPL	FOUT8		;SOME PLACES BEFORE DEC PNT. ; 小数点前有一些位
FOUT39: LDY	FBUFPT		;GET POINTER TO OUTPUT. ; 获取指向输出的指针
	LDAI	"."		;PUT IN "." ; 放入 "."
	INY
	STA	FBUFFR-1,Y
	TXA
	BEQ	FOUT16
	LDAI	"0"		;GET THE ENSUING ZERO. ; 获取后续的零
	INY
	STA	FBUFFR-1,Y
FOUT16: STY	FBUFPT		;SAVE FOR LATER. ; 保存供后续使用
FOUT8:	LDYI	0
FOUTIM: LDXI	200		;FIRST PASS THRU, ACCX HAS MSB SET. ; 第一次通过，ACCX 设置了 MSB
FOUT2:	LDA	FACLO
	CLC
	ADC	FOUTBL+2+ADDPRC,Y
	STA	FACLO
	LDA	FACMO
	ADC	FOUTBL+1+ADDPRC,Y
	STA	FACMO
IFN	ADDPRC,<                 ; 如果定义了 ADDPRC
	LDA	FACMOH
	ADC	FOUTBL+1,Y
	STA	FACMOH>
	LDA	FACHO
	ADC	FOUTBL,Y
	STA	FACHO
	INX			;IT WAS DONE YET ANOTHER TIME. ; 它又被完成了一次
	BCS	FOUT41
	BPL	FOUT2
	BMI	FOUT40
FOUT41: BMI	FOUT2
FOUT40: TXA
	BCC	FOUTYP		;CAN USE ACCA AS IS. ; 可以按原样使用 ACCA
	EORI	377		;FIND 11.-[A]. ; 找到 11.-[A]
	ADCI	12		;C IS STILL ON TO COMPLETE NEGATION. ; C 仍开启以完成取负
				;AND WILL ALWAYS BE ON AFTER. ; 并且之后将始终开启
FOUTYP: ADCI	"0"-1		;GET A CHARACTER TO PRINT. ; 获取要打印的字符
	REPEAT	3+ADDPRC,<INY>	;BUMP POINTER UP. ; 指针增加
	STY	FDECPT
	LDY	FBUFPT
	INY			;POINT TO PLACE TO STORE OUTPUT. ; 指向存储输出的位置
	TAX
	ANDI	177		;GET RID OF MSB. ; 去除 MSB
	STA	FBUFFR-1,Y
	DEC	DECCNT
	BNE	STXBUF		;NOT TIME FOR DP YET. ; 还不是小数点的时机
	LDAI	"."
	INY
	STA	FBUFFR-1,Y,	;STORE DP. ; 存储小数点
STXBUF: STY	FBUFPT		;STORE PNTR FOR LATER. ; 存储指针供后续使用
	LDY	FDECPT
FOUTCM: TXA			;COMPLEMENT ACCX ; 对 ACCX 取补
	EORI	377		;COMPLEMENT ACCA. ; 对 ACCA 取补
	ANDI	200		;SAVE ONLY MSB. ; 仅保存 MSB
	TAX
	CPYI	FDCEND-FOUTBL
IFN	TIME,<
	BEQ	FOULDY
	CPYI	TIMEND-FOUTBL>
	BNE	FOUT2		;CONTINUE WITH OUTPUT. ; 继续输出
FOULDY: LDY	FBUFPT		;GET BACK OUTPUT PNTR. ; 取回输出指针
FOUT11: LDA	FBUFFR-1,Y,	;REMOVE TRAILING ZEROES. ; 去除尾随零
	DEY
	CMPI	"0"
	BEQ	FOUT11
	CMPI	"."
	BEQ	FOUT12		;RUN INTO DP. STOP. ; 遇到小数点。停止
	INY			;SOMETHING ELSE. SAVE IT. ; 其他内容。保存它
FOUT12: LDAI	"+"
	LDX	TENEXP
	BEQ	FOUT17		;NO EXPONENT TO OUTPUT. ; 无指数输出
	BPL	FOUT14
	LDAI	0
	SEC
	SBC	TENEXP
	TAX
	LDAI	"-"		;EXPONENT IS NEGATIVE. ; 指数为负
FOUT14: STA	FBUFFR-1+2,Y,	;STORE SIGN OF EXP ; 存储指数的符号
	LDAI	"E"
	STA	FBUFFR-1+1,Y,	;STORE THE "E" CHARACTER. ; 存储 "E" 字符
	TXA
	LDXI	"0"-1
	SEC
FOUT15: INX			;MOVE CLOSER TO OUTPUT VALUE. ; 更接近输出值
	SBCI	12		;SUBTRACT 10. ; 减去 10
	BCS	FOUT15		;NOT NEGATIVE YET. ; 尚未为负
	ADCI	"0"+12		;GET SECOND OUTPUT CHARACTER. ; 获取第二个输出字符
	STA	FBUFFR-1+4,Y,	;STORE HIGH DIGIT. ; 存储高位数字
	TXA
	STA	FBUFFR-1+3,Y,	;STORE	LOW DIGIT. ; 存储低位数字
	LDAI	0		;PUT IN TERMINATOR. ; 放入终止符
	STA	FBUFFR-1+5,Y,
	BEQA	FOUT20		;RETURN. (ALWAYS BRANCHES). ; 返回（总是分支）
FOUT19: STA	FBUFFR-1,Y,	;STORE THE CHARACTER. ; 存储字符
FOUT17: LDAI	0		;A TERMINATOR. ; 终止符
	STA	FBUFFR-1+1,Y
FOUT20: LDWDI	FBUFFR
FPWRRT: RTS			;ALL DONE. ; 全部完成
FHALF:	200	;1/2 ; 二分之一
	000
ZERO:	000
	000
IFN	ADDPRC,<0>

;POWER OF TEN TABLE ; 十的幂表
IFE	ADDPRC,<
FOUTBL: 376	;-100000
	171
	140
	000	;10000
	047
	020
	377	;-1000
	374
	030
	000	;100
	000
	144
	377	;-10
	377
	366
	000	;1
	000
	001>

IFN	ADDPRC,<
FOUTBL: 372	;-100,000,000
	012
	037
	000
	000	;10,000,000
	230
	226
	200
	377	;-1,000,000
	360
	275
	300
	000	;100,000
	001
	206
	240
	377	;-10,000
	377
	330
	360
	000	;1000
	000
	003
	350
	377	;-100
	377
	377
	234
	000	;10
	000
	000
	012
	377	;-1
	377
	377
	377>
FDCEND:
IFN	TIME,<
	377	; -2160000 FOR TIME CONVERTER. ; 用于时间转换器的 -2160000
	337
	012
	200
	000	; 216000
	003
	113
	300
	377	; -36000
	377
	163
	140
	000	; 3600
	000
	016
	020
	377	; -600
	377
	375
	250
	000	; 60
	000
	000
	074
TIMEND:>

PAGE
SUBTTL	EXPONENTIATION AND SQUARE ROOT FUNCTION. ; 子标题：乘幂和平方根函数
	;SQUARE ROOT FUNCTION --- SQR(A) ;平方根函数 --- SQR(A)
	;USE SQR(X)=X^.5 ;使用 SQR(X)=X^.5
SQR:	JSR	MOVAF		;MOVE FAC INTO ARG. ; 将 FAC 移动到 ARG
	LDWDI	FHALF
	JSR	MOVFM		;PUT MEMORY INTO FAC. ; 将内存放入 FAC
				;LAST THING FETCHED IS FACEXP. INTO ACCX. ; 最后获取的是 FACEXP。进入 ACCX
;	JMP	FPWRT		;FALL INTO FPWRT. ; 落入 FPWRT

	;EXPONENTIATION ---  X^Y. ;乘幂 --- X^Y
	;N.B.  0^0=1 ;注意：0^0=1 ;首先检查 Y=0。如果是，结果为 1
	;FIRST CHECK IF Y=0. IF SO, THE RESULT IS 1. ;接下来检查 X=0。如果是，结果为 0
	;NEXT CHECK IF X=0. IF SO THE RESULT IS 0. ;然后检查 X>0。如果不是，检查 Y 是否为整数
	;THEN CHECK IF X.GT.0. IF NOT CHECK THAT Y IS AN INTEGER. ;如果是，对 X 取负，以便 LOG 不会给出 FCERR
	;IF SO, NEGATE X, SO THAT LOG DOESN'T GIVE FCERR. ;如果 X 为负且 Y 为奇数，对 EXP 返回的结果取负
	;IF X IS NEGATIVE AND Y IS ODD, NEGATE THE RESULT ;使用 X^Y=EXP((Y*LOG(X))) 计算结果
	;RETURNED BY EXP.
	;TO COMPUTE THE RESULT USE X^Y=EXP((Y*LOG(X)).
FPWRT:	BEQ	EXP		;IF FAC=0, JUST EXPONENTIATE THAT. ; 如果 FAC=0，仅对其进行乘幂
	LDA	ARGEXP		;IS X=0? ; X=0 吗？
	BNE	FPWRT1
	JMP	ZEROF1		;ZERO FAC. ; 清零 FAC
FPWRT1: LDXYI	TEMPF3		;SAVE FOR LATER IN A TEMP. ; 保存到临时变量中供后续使用
	JSR	MOVMF
	;Y=0 ALREADY. GOOD IN CASE NO ONE CALLS INT. ; Y 已为 0。如果无人调用 INT，这样很好
	LDA	ARGSGN
	BPL	FPWR1		;NO PROBLEMS IF X.GT.0. ; 如果 X>0 则无问题
	JSR	INT		;INTEGERIZE THE FAC. ; 将 FAC 整数化
	LDWDI	TEMPF3		;GET ADDR OF COMPERAND. ; 获取比较数的地址
	JSR	FCOMP		;EQUAL? ; 相等吗？
	BNE	FPWR1		;LEAVE X NEG. LOG WILL BLOW HIM OUT. ; 保持 X 为负。LOG 将使其出错
				;A=-1 AND Y IS IRRELEVANT. ; A=-1 且 Y 无关紧要
	TYA			;NEGATE X. MAKE POSITIVE. ; 对 X 取负。使其为正
	LDY	INTEGR		;GET EVENNESS. ; 获取奇偶性
FPWR1:	JSR	MOVFA1		;ALTERNATE ENTRY POINT. ; 备用入口点
	TYA
	PHA			;SAVE EVENNESS FOR LATER. ; 保存奇偶性供后续使用
	JSR	LOG		;FIND LOG. ; 查找对数
	LDWDI	TEMPF3		;MULTIPLY FAC TIMES LOG(X). ; FAC 乘以 LOG(X)
	JSR	FMULT
	JSR	EXP		;EXPONENTIATE THE FAC. ; 对 FAC 进行乘幂
	PLA
	LSR	A,		;IS IT EVEN? ; 是偶数吗？
	BCC	NEGRTS		;YES. OR X.GT.0. ; 是。或 X>0
	;NEGATE THE NUMBER IN FAC. ; 对 FAC 中的数字取负
NEGOP:	LDA	FACEXP
	BEQ	NEGRTS
	COM	FACSGN
NEGRTS: RTS

PAGE
SUBTTL	EXPONENTIATION FUNCTION. ; 子标题：乘幂函数
	;FIRST SAVE THE ORIGINAL ARGUMENT AND MULTIPLY THE FAC BY ;首先保存原始参数并将 FAC 乘以 LOG2(E)
	;LOG2(E). THE RESULT IS USED TO DETERMINE IF OVERFLOW ;结果用于确定是否会发生溢出，因为 EXP(X)=2^(X*LOG2(E))，
	;WILL OCCUR SINCE EXP(X)=2^(X*LOG2(E)) WHERE ;其中 LOG2(E)=LOG(E) 以 2 为底
	;LOG2(E)=LOG(E) BASE 2. THEN SAVE THE INTEGER PART OF ;然后保存其整数部分以在最后缩放答案
	;THIS TO SCALE THE ANSWER AT THE END. SINCE ;因为 2^Y=2^INT(Y)*2^(Y-INT(Y)) 且 2^INT(Y) 易于计算
	;2^Y=2^INT(Y)*2^(Y-INT(Y)) AND 2^INT(Y) IS EASY TO COMPUTE.
	;NOW COMPUTE 2^(X*LOG2(E)-INT(X*LOG2(E)) BY ;现在通过 P(LN(2)*(INT(X*LOG2(E))+1)-X) 计算 
	;P(LN(2)*(INT(X*LOG2(E))+1)-X) WHERE P IS AN APPROXIMATION ;2^(X*LOG2(E)-INT(X*LOG2(E)))，其中 P 是近似多项式
	;POLYNOMIAL. THE RESULT IS THEN SCALED BY THE POWER OF 2 ;然后结果由先前保存的 2 的幂缩放
	;PREVIOUSLY SAVED.

LOGEB2: 201			;LOG(E) BASE 2. ; 以 2 为底的 LOG(E)
	070
	252
	073
IFN	ADDPRC,<051>

ife	addprc,<
expcon: 6	; degree -1. ; 次数 -1
	164	; .00021702255
	143
	220
	214
	167	; .0012439688
	043
	014
	253
	172	; .0096788410
	036
	224
	000
	174	; .055483342
	143
	102
	200
	176	; .24022984
	165
	376
	320
	200	; .69314698
	061
	162
	025
	201	; 1.0
	000
	000
	000>


IFN	ADDPRC,<
EXPCON: 7	;DEGREE-1 ; 次数-1
	161	; .000021498763697
	064
	130
	076
	126
	164	; .00014352314036
	026
	176
	263
	033
	167	; .0013422634824
	057
	356
	343
	205
	172	; .0096140170119
	035
	204
	034
	052
	174	; .055505126860
	143
	131
	130
	012
	176	; .24022638462
	165
	375
	347
	306
	200	; .69314718608
	061
	162
	030
	020
	201	; 1.0
	000
	000
	000
	000>

EXP:
	LDWDI	LOGEB2		;MULTIPLY BY LOG(E) BASE 2. ; 乘以以 2 为底的 LOG(E)
	JSR	FMULT
	LDA	FACOV
	ADCI	120
	BCC	STOLD
	JSR	INCRND
STOLD:	STA	OLDOV
	JSR	MOVEF		;TO SAVE IN ARG WITHOUT ROUND. ; 保存到 ARG 中而不舍入
	LDA	FACEXP
	CMPI	210		;IF ABS(FAC) .GE. 128, TOO BIG. ; 如果 ABS(FAC) ≥ 128，太大
	BCC	EXP1
GOMLDV: JSR	MLDVEX		;OVERFLOW OR OVERFLOW. ; 溢出或溢出
EXP1:	JSR	INT
	LDA	INTEGR	;GET LOW PART. ; 获取低位部分
	CLC
	ADCI	201
	BEQ	GOMLDV		;OVERFLOW OR OVERFLOW !! ; 溢出或溢出！！
	SEC
	SBCI	1		;SUBTRACT 1. ; 减去 1
	PHA			;SAVE A WHILE. ; 暂时保存
	LDXI	4+ADDPRC	;PREP TO SWAP FAC AND ARG. ; 准备交换 FAC 和 ARG
SWAPLP: LDA	ARGEXP,X
	LDY	FACEXP,X
	STA	FACEXP,X
	STY	ARGEXP,X
	DEX
	BPL	SWAPLP
	LDA	OLDOV
	STA	FACOV
	JSR	FSUBT
	JSR	NEGOP		;NEGATE FAC. ; 对 FAC 取负
	LDWDI	EXPCON
	JSR	POLY
	CLR	ARISGN		;MULTIPLY BY POSITIVE 1.0. ; 乘以正的 1.0
	PLA			;GET SCALE FACTOR. ; 获取缩放因子
	JSR	MLDEXP		;MODIFY FACEXP AND CHECK FOR OVERFLOW. ; 修改 FACEXP 并检查溢出
	RTS			;HAS TO DO JSR DUE TO PULAS IN MULDIV. ; 由于 MULDIV 中的 PULAS，必须执行 JSR


PAGE
SUBTTL	POLYNOMIAL EVALUATOR AND THE RANDOM NUMBER GENERATOR. ; 子标题：多项式求值器和随机数生成器
	;EVALUATE P(X^2)*X ;求值 P(X^2)*X
	;POINTER TO DEGREE IS IN [Y,A]. ;指向次数的指针在 [Y,A] 中
	;THE CONSTANTS FOLLOW THE DEGREE. ;常数在次数之后
	;FOR X=FAC, COMPUTE: ;对于 X=FAC，计算：
	; C0*X+C1*X^3+C2*X^5+C3*X^7+...+C(N)*X^(2*N+1)
POLYX:	STWD	POLYPT		;RETAIN POLYNOMIAL POINTER FOR LATER. ; 保留多项式指针供后续使用
	JSR	MOV1F		;SAVE FAC IN FACTMP. ; 将 FAC 保存在 FACTMP 中
	LDAI	TEMPF1
	JSR	FMULT		;COMPUTE X^2. ; 计算 X^2
	JSR	POLY1		;COMPUTE P(X^2). ; 计算 P(X^2)
	LDWDI	TEMPF1
	JMP	FMULT		;MULTIPLY BY FAC AGAIN. ; 再次乘以 FAC

	;POLYNOMIAL EVALUATOR. ;多项式求值器
	;POINTER TO DEGREE IS IN [Y,A]. ;指向次数的指针在 [Y,A] 中
	;COMPUTE: ;计算：
	; C0+C1*X+C2*X^2+C3*X^3+C4*X^4+...+C(N-1)*X^(N-1)+C(N)*X^N.
POLY:	STWD	POLYPT
POLY1:	JSR	MOV2F		;SAVE FAC. ; 保存 FAC
	LDADY	POLYPT
	STA	DEGREE
	LDY	POLYPT
	INY
	TYA
	BNE	POLY3
	INC	POLYPT+1
POLY3:	STA	POLYPT
	LDY	POLYPT+1
POLY2:	JSR	FMULT
	LDWD	POLYPT		;GET CURRENT POINTER. ; 获取当前指针
	CLC
	ADCI	4+ADDPRC
	BCC	POLY4
	INY
POLY4:	STWD	POLYPT
	JSR	FADD		;ADD IN CONSTANT. ; 加入常数
	LDWDI	TEMPF2		;MULTIPLY THE ORIGINAL FAC. ; 乘以原始 FAC
	DEC	DEGREE		;DONE? ; 完成？
	BNE	POLY2
RANDRT: RTS			;YES. ; 是

	;PSUEDO-RANDOM NUMBER GENERATOR. ;伪随机数生成器
	;IF ARG=0, THE LAST RANDOM NUMBER GENERATED IS RETURNED. ;如果 ARG=0，返回最后生成的随机数
	;IF ARG .LT. 0, A NEW SEQUENCE OF RANDOM NUMBERS IS ;如果 ARG < 0，使用参数启动新的随机数序列
	;STARTED USING THE ARGUMENT.
	;   TO FORM THE NEXT RANDON NUMBER IN THE SEQUENCE, ;   要形成序列中的下一个随机数，
	;MULTIPLY THE PREVIOUS RANDOM NUMBER BY A RANDOM CONSTANT ;将前一个随机数乘以一个随机常数并加入另一个随机常数
	;AND ADD IN ANOTHER RANDOM CONSTANT. THE THEN HO ;然后交换 HO 和 LO 字节，
	;AND LO BYTES ARE SWITCHED, THE EXPONENT IS PUT WHERE ;将指数放在将由 NORMAL 移入的位置，
	;IT WILL BE SHIFTED IN BY NORMAL, AND THE EXPONENT IN THE FAC ;并将 FAC 中的指数设置为 200，
	;IS SET TO 200 SO THE RESULT WILL BE LESS THAN 1. THIS ;因此结果将小于 1
	;IS THEN NORMALIZED AND SAVED FOR THE NEXT TIME. ;然后将其规范化并保存供下次使用
	;THE HO AND LOW BYTES WERE SWITCHED SO THERE WILL BE A ;交换 HO 和 LO 字节是为了随机获得小于或大于 .5 的数字
	;RANDOM CHANCE OF GETTING A NUMBER LESS THAN OR GREATER
	;THAN .5 .

RMULZC: 230
	065
	104
	172
RADDZC: 150
	050
	261
	106

RND:	JSR	SIGN		;GET SIGN INTO ACCX. ; 将符号获取到 ACCX
IFN	REALIO-3,<
	TAX>			;GET INTO ACCX, SINCE "MOVFM" USES ACCX. ; 获取到 ACCX，因为 "MOVFM" 使用 ACCX
	BMI	RND1		;START NEW SEQUENCE IF NEGATIVE. ; 如果为负，启动新序列
IFE	REALIO-3,<
	BNE	QSETNR
		;TIMERS ARE AT 9044(L0),45(HI),48(LO),49(HI) HEX. ;计时器位于 9044(L0)、45(HI)、48(LO)、49(HI) 十六进制
		;FIRST TWO ARE ALWAYS FREE RUNNING. ;前两个始终自由运行
		;SECOND PAIR IS NOT. LO IS FREER THAN HI THEN. ;第二对不是。LO 比 HI 更自由
		;SO ORDER IN FAC IS 44,48,45,49. ;因此 FAC 中的顺序是 44,48,45,49
	LDA	CQHTIM
	STA	FACHO
	LDA	CQHTIM+4
	STA	FACMOH
	LDA	CQHTIM+1
	STA	FACMO
	LDA	CQHTIM+5
	STA	FACLO
	JMP	STRNEX>
QSETNR: LDWDI	RNDX		;GET LAST ONE INTO FAC. ; 将最后一个获取到 FAC
	JSR	MOVFM
IFN	REALIO-3,<
	TXA			;FAC WAS ZERO? ; FAC 为零吗？
	BEQ	RANDRT>		;RESTORE LAST ONE. ; 恢复最后一个
	LDWDI	RMULZC		;MULTIPLY BY RANDOM CONSTANT. ; 乘以随机常数
	JSR	FMULT
	LDWDI	RADDZC
	JSR	FADD		;ADD RANDOM CONSTANT. ; 加入随机常数
RND1:	LDX	FACLO
	LDA	FACHO
	STA	FACLO
	STX	FACHO		;REVERSE HO AND LO. ; 反转 HO 和 LO
IFE	REALIO-3,<
	LDX	FACMOH
	LDA	FACMO
	STA	FACMOH
	STX	FACMO>
STRNEX: CLR	FACSGN		;MAKE NUMBER POSITIVE. ; 使数字为正
	LDA	FACEXP		;PUT EXP WHERE IT WILL ; 将指数放在它将
	STA	FACOV		;BE SHIFTED IN BY NORMAL. ; 由 NORMAL 移入的位置
	LDAI	200
	STA	FACEXP		;MAKE RESULT BETWEEN 0 AND 1. ; 使结果在 0 和 1 之间
	JSR	NORMAL		;NORMALIZE. ; 规范化
	LDXYI	RNDX
GMOVMF: JMP	MOVMF		;PUT NEW ONE INTO MEMORY. ; 将新的放入内存

PAGE
SUBTTL	SINE, COSINE AND TANGENT FUNCTIONS. ; 子标题：正弦、余弦和正切函数
IFE	KIMROM,<
	;COSINE FUNCTION. ;余弦函数
	;USE COS(X)=SIN(X+PI/2) ;使用 COS(X)=SIN(X+PI/2)
COS:	LDWDI	PI2		;PNTR TO PI/2. ; 指向 PI/2
	JSR	FADD		;ADD IT IN. ; 加入它
				;FALL INTO SIN. ; 落入 SIN


	;SINE FUNCTION. ;正弦函数
	;USE IDENTITIES TO GET FAC IN QUADRANTS I OR IV. ;使用恒等式将 FAC 置于象限 I 或 IV
	;THE FAC IS DIVIDED BY 2*PI AND THE INTEGER PART IS IGNORED ;将 FAC 除以 2*PI 并忽略整数部分，
	;BECAUSE SIN(X+2*PI)=SIN(X). THEN THE ARGUMENT CAN BE COMPARED ；因为 SIN(X+2*PI)=SIN(X)
	;WITH PI/2 BY COMPARING THE RESULT OF THE DIVISION ;然后通过将除法结果与 PI/2/(2*PI)=1/4 进行比较，
	;WITH PI/2/(2*PI)=1/4. ;可以将参数与 PI/2 进行比较
	;IDENTITIES ARE THEN USED TO GET THE RESULT IN QUADRANTS ;然后使用恒等式将结果置于象限 I 或 IV
	;I OR IV. AN APPROXIMATION POLYNOMIAL IS THEN USED TO ;然后使用近似多项式计算 SIN(X)
	;COMPUTE SIN(X).
SIN:	JSR	MOVAF
	LDWDI	TWOPI		;GET PNTR TO DIVISOR. ; 获取指向除数的指针
	LDX	ARGSGN		;GET SIGN OF RESULT. ; 获取结果的符号
	JSR	FDIVF
	JSR	MOVAF		;GET RESULT INTO ARG. ; 将结果获取到 ARG
	JSR	INT		;INTEGERIZE FAC. ; 将 FAC 整数化
	CLR	ARISGN		;ALWAYS HAVE THE SAME SIGN. ; 始终具有相同的符号
	JSR	FSUBT		;KEEP ONLY THE FRACTIONAL PART. ; 仅保留小数部分
	LDWDI	FR4		;GET PNTR TO 1/4. ; 获取指向 1/4 的指针
	JSR	FSUB		;COMPUTE 1/4-FAC. ; 计算 1/4-FAC
	LDA	FACSGN		;SAVE SIGN FOR LATER. ; 保存符号供后续使用
	PHA
	BPL	SIN1		;FIRST QUADRANT. ; 第一象限
	JSR	FADDH		;ADD 1/2 TO FAC. ; 向 FAC 加 1/2
	LDA	FACSGN		;SIGN IS NEGATIVE? ; 符号为负？
	BMI	SIN2
	COM	TANSGN		;QUADRANTS II AND III COME HERE. ; 象限 II 和 III 来到这里
SIN1:	JSR	NEGOP		;IF POSITIVE, NEGATE IT. ; 如果为正，对其取负
SIN2:	LDWDI	FR4		;POINTER TO 1/4. ; 指向 1/4 的指针
	JSR	FADD		;ADD IT IN. ; 加入它
	PLA			;GET ORIGINAL QUADRANT. ; 获取原始象限
	BPL	SIN3
	JSR	NEGOP		;IF NEGATIVE, NEGATE RESULT. ; 如果为负，对结果取负
SIN3:	LDWDI	SINCON
GPOLYX: JMP	POLYX		;DO APPROXIMATION POLYNOMIAL. ; 执行近似多项式


	;TANGENT FUNCTION. ; 正切函数
TAN:	JSR	MOV1F		;MOVE FAC INTO TEMPORARY. ; 将 FAC 移动到临时变量
	CLR	TANSGN		;REMEMBER WHETHER TO NEGATE. ; 记住是否取负
	JSR	SIN		;COMPUTE THE SIN. ; 计算正弦
	LDXYI	TEMPF3
	JSR	GMOVMF		;PUT SIGN INTO OTHER TEMP. ; 将符号放入另一个临时变量
	LDWDI	TEMPF1
	JSR	MOVFM		;PUT THIS MEMORY LOC INTO FAC. ; 将此内存位置放入 FAC
	CLR	FACSGN		;START OFF POSITIVE. ; 以正数开始
	LDA	TANSGN
	JSR	COSC		;COMPUTE COSINE. ; 计算余弦
	LDWDI	TEMPF3		;ADDRESS OF SINE VALUE. ; 正弦值的地址
GFDIV:	JMP	FDIV		;DIVIDE SINE BY COSINE AND RETURN. ; 正弦除以余弦并返回
COSC:	PHA
	JMP	SIN1

PI2:	201	;PI/2 ; π/2
	111
	017
	333-ADDPRC
IFN	ADDPRC,<242>
TWOPI:	203	;2*PI. ; 2π
	111
	017
	333-ADDPRC
IFN	ADDPRC,<242>
FR4:	177	;1/4 ; 四分之一
	000
	000
	0000
IFN	ADDPRC,<0>
IFE ADDPRC,<SINCON:	4	;DEGREE-1. ; 次数-1
	206	;39.710899
	036
	327
	373
	207	;-76.574956
	231
	046
	145
	207	;81.602231
	043
	064
	130
	206	;-41.341677
	245
	135
	341
	203	;6.2831853
	111
	017
	333>

IFN	ADDPRC,<
SINCON: 5		;DEGREE-1 ; 次数-1
	204	; -14.381383816
	346
	032
	055
	033
	206	; 42.07777095
	050
	007
	373
	370
	207	; -76.704133676
	231
	150
	211
	001
	207	; 81.605223690
	043
	065
	337
	341
	206	; -41.34170209
	245
	135
	347
	050
	203	; 6.2831853070
	111
	017
	332
	242
	241	; 7.2362932E7
	124
	106
	217
	23
	217	; 73276.2515
	122
	103
	211
	315>
PAGE
SUBTTL	ARCTANGENT FUNCTION. ; 子标题：反正切函数
	;USE IDENTITIES TO GET ARG BETWEEN 0 AND 1 AND THEN USE AN ;使用恒等式将 ARG 置于 0 和 1 之间，
	;APPROXIMATION POLYNOMIAL TO COMPUTE ARCTAN(X). ;然后使用近似多项式计算 ARCTAN(X)
ATN:	LDA	FACSGN		;WHAT IS SIGN? ; 符号是什么？
	PHA			;(MEANWHILE SAVE FOR LATER.) ; （同时保存供后续使用）
	BPL	ATN1
	JSR	NEGOP		;IF NEGATIVE, NEGATE FAC. ; 如果为负，对 FAC 取负
				;USE ARCTAN(X)=-ARCTAN(-X) . ; 使用 ARCTAN(X)=-ARCTAN(-X)
ATN1:	LDA	FACEXP
	PHA			;SAVE THIS TOO FOR LATER. ; 这也保存供后续使用
	CMPI	201		;SEE IF FAC .GE. 1.0 . ; 查看 FAC ≥ 1.0 吗？
	BCC	ATN2		;IT IS LESS THAN 1. ; 它小于 1
	LDWDI	FONE		;GET PNTR TO 1.0 . ; 获取指向 1.0 的指针
	JSR	FDIV		;COMPUTE RECIPROCAL. ; 计算倒数
				;USE ARCTAN(X)=PI/2-ARCTAN(1/X) . ; 使用 ARCTAN(X)=PI/2-ARCTAN(1/X)
ATN2:	LDWDI	ATNCON		;PNTR TO ARCTAN CONSTANTS. ; 指向反正切常数的指针
	JSR	POLYX
	PLA
	CMPI	201		;WAS ORIGINAL ARGUMENT .LT. 1 ? ; 原始参数 < 1 吗？
	BCC	ATN3		;YES. ; 是
	LDWDI	PI2
	JSR	FSUB		;SUBTRACT ARCTAGN FROM PI/2. ; 从 PI/2 中减去 ARCTAGN
ATN3:	PLA			;WAS ORIGINAL ARGUMENT POSITIVE? ; 原始参数为正吗？
	BPL	ATN4		;YES. ; 是
	JMP	NEGOP		;IF NEGATIVE, NEGATE RESULT. ; 如果为负，对结果取负
ATN4:	RTS			;ALL DONE. ; 全部完成

IFE	ADDPRC,<
ATNCON:	 10	;DEGREE-1. ; 次数-1
	170	;.0028498896
	072
	305
	067
	173	;-.016068629
	203
	242
	134
	174	;.042691519
	056
	335
	115
	175	;-.075042945
	231
	260
	036
	175	;.10640934
	131
	355
	044
	176	;-.14203644
	221
	162
	000
	176	;.19992619
	114
	271
	163
	177	;.-33333073
	252
	252
	123
	201	;1.0
	000
	000
	000>

IFN	ADDPRC,<
ATNCON: 13	;DEGREE-1 ; 次数-1
	166	; -.0006847939119
	263
	203
	275
	323
	171	; .004850942156
	036
	364
	246
	365
	173	; -.01611170184
	203
	374
	260
	020
	174	; .03420963805
	014
	037
	147
	312
	174	; -.05427913276
	336
	123
	313
	301
	175	; .07245719654
	024
	144
	160
	114
	175	; -.08980239538
	267
	352
	121
	172
	175	; .1109324134
	143
	060
	210
	176
	176	; -.1428398077
	222
	104
	231
	072
	176	; .1999991205
	114
	314
	221
	307
	177	; -.3333333157
	252
	252
	252
	023
	201	; 1.0
	000
	000
	000
	000>>
PAGE
SUBTTL	SYSTEM INITIALIZATION CODE. ; 子标题：系统初始化代码
RADIX	10		;IN ALL NON-MATH-PACKAGE CODE. ; 在所有非数学包代码中
; THIS INITIALIZES THE BASIC INTERPRETER FOR THE M6502 AND SHOULD BE ; 这将为 M6502 初始化 BASIC 解释器，
; LOCATED WHERE IT WILL BE WIPED OUT IN RAM IF CODE IS ALL IN RAM. ;并且如果代码全部在 RAM 中，应位于在 RAM 中会被擦除的位置

IFE	ROMSW,<
	BLOCK	1>		;SO ZEROING AT TXTTAB DOESN'T PREVENT ; 因此在 TXTTAB 处清零不会阻止
				;RESTARTING INIT ; 重新启动初始化
INITAT: INC	CHRGET+7	;INCREMENT THE WHOLE TXTPTR. ; 增加整个 TXTPTR
	BNE	CHZGOT
	INC	CHRGET+8
CHZGOT: LDA	60000		;A LOAD WITH AN EXT ADDR. ; 带有外部地址的加载
	CMPI	":"		;IS IT A ":"? ; 是 ":" 吗？
	BCS	CHZRTS		;IT IS .GE. ":". ; 它是 ≥ ":"
	CMPI	" "		;SKIP SPACES. ; 跳过空格
	BEQ	INITAT
	SEC
	SBCI	"0"		;ALL CHARS .GT. "9" HAVE RET'D SO ; 所有 > "9" 的字符都已返回，因此
	SEC
	SBCI	^D256-"0"		;SEE IF NUMERIC. ; 查看是否为数字
				;TURN CARRY ON IF NUMERIC. ; 如果是数字，则开启进位
				;ALSO, SETZ IF NULL. ; 另外，如果为 NULL 则设置 Z
CHZRTS: RTS			;RETURN TO CALLER. ; 返回调用者

	128			;LOADED OR FROM ROM. ; 已加载或来自 ROM
	79			;THE INITIAL RANDOM NUMBER. ; 初始随机数
	199
	82
IFN	ADDPRC,<88>
IFN REALIO-3,<
IFE	KIMROM,<
TYPAUT: LDWDI	AUTTXT
	JSR	STROUT>>
INIT:
IFN	REALIO-3,<
	LDXI	255		;MAKE IT LOOK DIRECT IN CASE OF ; 使其看起来直接，以防
	STX	CURLIN+1>	;ERROR MESSAGE. ; 错误消息
IFN	STKEND-511,<
	LDXI	STKEND-256>
	TXS
IFN	REALIO-3,<
	LDWDI	INIT		;ALLOW RESTART. ; 允许重新启动
	STWD	START+1
	STWD	RDYJSR+1	;RTS HERE ON ERRORS. ; 错误时在此 RTS
	LDWDI	AYINT
	STWD	ADRAYI
	LDWDI	GIVAYF
	STWD	ADRGAY>
	LDAI	76		;JMP INSTRUCTION. ; JMP 指令
IFE	REALIO,<HRLI 1,^O1000>	;MAKE AN INST. ; 创建指令
IFN	REALIO-3,<
	STA	START
	STA	RDYJSR>
	STA	JMPER
IFN	ROMSW,<
	STA	USRPOK
	LDWDI	FCERR
	STWD	USRPOK+1>
	LDAI	LINLEN		;THESE MUST BE NON-ZERO SO CHEAD WILL ; 这些必须非零，以便 CHEAD 将
	STA	LINWID		;WORK AFTER MOVING A NEW LINE IN BUF ; 在将新行移动到 BUF 后工作
				;INTO THE PROGRAM ; 到程序中
	LDAI	NCMPOS
	STA	NCMWID
	LDXI	RNDX+4-CHRGET
MOVCHG: LDA	INITAT-1,X,
	STA	CHRGET-1,X,	;MOVE TO RAM. ; 移动到 RAM
	DEX
	BNE	MOVCHG
	LDAI	STRSIZ
	STA	FOUR6
	TXA			;SET CONST IN RAM. ; 在 RAM 中设置常量
	STA	BITS
IFN EXTIO,<
	STA	CHANNL>
	STA	LASTPT+1
IFN	NULCMD,<
	STA	NULCNT>
	PHA			;PUT ZERO AT THE END OF THE STACK ; 在堆栈末尾放入零
				;SO FNDFOR WILL STOP ; 以便 FNDFOR 将停止
IFN	REALIO,<
	STA	CNTWFL>		;BE TALKATIVE. ; 健谈
IFN	BUFPAG,<
	INX			;MAKE [X]=1 ; 使 [X]=1
	STX	BUF-3		;SET PRE-BUF BYTES NON-ZERO FOR CHEAD ; 为 CHEAD 设置前缓冲字节非零
	STX	BUF-4>
IFN	REALIO-3,<
	JSR	CRDO>		;TYPE A CR. ; 打印回车
	LDXI	TEMPST
	STX	TEMPPT		;SET UP STRING TEMPORARIES. ; 设置字符串临时变量
IFN	REALIO!LONGI,<
IFN	REALIO-3,<
	LDWDI	MEMORY
	JSR	STROUT
	JSR	QINLIN		;GET A LINE OF INPUT. ; 获取一行输入
	STXY	TXTPTR		;READ THIS ! ; 读取此内容！
	JSR	CHRGET		;GET THE FIRST CHARACTER. ; 获取第一个字符
IFE	KIMROM,<
	CMPI	"A"		;IS IT AN "A"? ; 是 "A" 吗？
	BEQ	TYPAUT>		;YES TYPE AUTHOR'S NAME. ; 是，打印作者姓名
	TAY			;NULL INPUT? ; 空输入？
	BNE	USEDE9>		;NO. ; 否
IFE	REALIO-3,<
	LDYI	RAMLOC/^D256>
IFN	REALIO-3,<
IFE	ROMSW,<
	LDWDI	LASTWR>		;YES GET PNTR TO LAST WORD. ; 是，获取指向最后一个字的指针
IFN	ROMSW,<
	LDWDI	RAMLOC>>
IFN	ROMSW,<
	STWD	TXTTAB>		;SET UP START OF PROGRAM LOCATION ; 设置程序起始位置
	STWD	LINNUM
IFE	REALIO-3,<
	TAY>
IFN	REALIO-3,<
	LDYI	0>
LOOPMM: INC	LINNUM
	BNE	LOOPM1
	INC	LINNUM+1
IFE	REALIO-3,<
	BMI	USEDEC>
LOOPM1: LDAI	85		;PUT RANDOM INFO INTO MEM. ; 将随机信息放入内存
	STADY	LINNUM
	CMPDY	LINNUM		;WAS IT SAVED? ; 它被保存了吗？
	BNE	USEDEC		;NO. THAT IS END OF MEMORY. ; 否。那是内存的末尾
	ASL	A,		;LOOKS LIKE IT. TRY ANOTHER. ; 看起来是。尝试另一个
	STADY	LINNUM
	CMPDY	LINNUM		;WAS IT SAVED? ; 它被保存了吗？
IFN	REALIO-3,<
	BNE	USEDEC>		;NO. THIS IS THE END. ; 否。这是末尾
IFN	REALIO-2,<
	BEQ	LOOPMM>
IFE	REALIO-2,<
	BNE	USEDEC
	CMP	0		;SEE IF HITTING PAGE 0 ; 查看是否碰到第 0 页
	BNE	LOOPMM
	LDAI	76
	STA	0
	BNEA	USEDEC>
IFN	REALIO-3,<
USEDE9: JSR	CHRGOT		;GET CURRENT CHARACTER. ; 获取当前字符
	JSR	LINGET		;GET DECIMAL ARGUMENT. ; 获取十进制参数
	TAY			;MAKE SURE A TERMINATOR EXISTS. ; 确保存在终止符
	BEQ	USEDEC		;IT DOES. ; 它存在
	JMP	SNERR>		;IT DOESN'T. ; 它不存在
USEDEC: LDWD	LINNUM		;GET SIZE OF MEMORY INPUT. ; 获取内存输入的大小
USEDEF: >			;HIGHEST ADDRESS. ; 最高地址
IFE	REALIO!LONGI,<
	LDWDI	16190>		;A STRANGE NUMBER. ; 一个奇怪的数字
	STWD	MEMSIZ		;THIS IS THE SIZE OF MEMORY. ; 这是内存的大小
	STWD	FRETOP		;TOP OF STRINGS TOO. ; 也是字符串的顶部
TTYW:
IFN	REALIO-3,<
IFN	REALIO!LONGI,<
	LDWDI	TTYWID
	JSR	STROUT
	JSR	QINLIN		;GET LINE OF INPUT. ; 获取输入行
	STXY	TXTPTR		;READ THIS ! ; 读取此内容！
	JSR	CHRGET		;GET FIRST CHARACTER. ; 获取第一个字符
	TAY			;TEST ACCA BUT DON'T AFFECT CARRY. ; 测试 ACCA 但不影响进位
	BEQ	ASKAGN
	JSR	LINGET		;GET ARGUMENT. ; 获取参数
	LDA	LINNUM+1
	BNE	TTYW		;WIDTH MUST BE .LT. 256. ; 宽度必须 < 256
	LDA	LINNUM
	CMPI	16		;WIDTH MUST BE GREATER THAN 16. ; 宽度必须大于 16
	BCC	TTYW
	STA	LINWID		;THAT IS THE LINE WIDTH. ; 那是行宽
MORCPS: SBCI	CLMWID		;COMPUTE POSITION BEYOND WHICH ; 计算超出此位置
	BCS	MORCPS		;THERE ARE NO MORE FIELDS. ; 没有更多字段
	EORI	255
	SBCI	CLMWID-2
	CLC
	ADC	LINWID
	STA	NCMWID>
ASKAGN:
IFE	ROMSW,<
IFN	REALIO!LONGI,<
	LDWDI	FNS
	JSR	STROUT
	JSR	QINLIN
	STXY	TXTPTR		;READ THIS ! ; 读取此内容！
	JSR	CHRGET
	LDXYI	INITAT		;DEFAULT. ; 默认
	CMPI	"Y"
	BEQ	HAVFNS		;SAVE ALL FUNCTIONS. ; 保存所有函数
	CMPI	"A"
	BEQ	OKCHAR		;SAVE ALL BUT ATN. ; 保存除 ATN 之外的所有函数
	CMPI	"N"
	BNE	ASKAGN		;BAD INPUT. ; 错误输入
				;SAVE NOTHING. ; 不保存任何内容
OKCHAR: LDXYI	FCERR
	STXY	ATNFIX		;GET RID OF ATN FUNCTION. ; 去除 ATN 函数
	LDXYI	ATN		;UNTIL WE KNOW THAT WE SHOULD DEL MORE. ; 直到我们知道应该删除更多
	CMPI	"A"
	BEQ	HAVFNS		;JUST GET RID OF ATN. ; 仅去除 ATN
	LDXYI	FCERR
	STXY	COSFIX		;GET RID OF THE REST. ; 去除其余部分
	STXY	TANFIX
	STXY	SINFIX
	LDXYI	COS		;AND GET RID OF ALL BACK TO "COS". ; 并去除所有回到 "COS" 的内容
HAVFNS:>
IFE	REALIO!LONGI,<
	LDXYI	INITAT-1>>>	;GET RID OF ALL UP TO "INITAT". ; 去除所有直到 "INITAT" 的内容
IFN	ROMSW,<
	LDXYI	RAMLOC
	STXY	TXTTAB>
	LDYI	0
	TYA
	STADY	TXTTAB		;SET UP TEXT TABLE. ; 设置文本表
	INC	TXTTAB
IFN	REALIO-3,<
	BNE	QROOM
	INC	TXTTAB+1>
QROOM:	LDWD	TXTTAB		;PREPARE TO USE "REASON". ; 准备使用 "REASON"
	JSR	REASON
IFE	REALIO-3,<
	LDWDI	FREMES
	JSR	STROUT>
IFN	REALIO-3,<
	JSR	CRDO>
	LDA	MEMSIZ		;COMPUTE [MEMSIZ]-[VARTAB]. ; 计算 [MEMSIZ]-[VARTAB]
	SEC
	SBC	TXTTAB
	TAX
	LDA	MEMSIZ+1
	SBC	TXTTAB+1
	JSR	LINPRT		;TYPE THIS VALUE. ; 打印此值
	LDWDI	WORDS		;MORE BULLSHIT. ; 更多废话
	JSR	STROUT
	JSR	SCRTCH		;SET UP EVERYTHING ELSE. ; 设置所有其他内容
IFE	REALIO-3,<
	JMP	READY>
IFN	REALIO-3,<
	LDWDI	STROUT
	STWD	RDYJSR+1
	LDWDI	READY
	STWD	START+1
	JMPD	START+1

IFE	ROMSW,<
FNS:	DT"WANT SIN-COS-TAN-ATN"
	0>
IFE	KIMROM,<
AUTTXT: ACRLF
	12			;ANOTHER LINE FEED. ; 另一个换行
	DT"WRITTEN "
	DT"BY WEILAND & GATES"
	ACRLF
	0>
MEMORY: DT"MEMORY SIZE"
	0
TTYWID:
IFE	KIMROM,<
	DT"TERMINAL ">
	DT"WIDTH"
	0>
WORDS:	DT" BYTES FREE"
IFN	REALIO-3,<
	ACRLF
	ACRLF>
IFE	REALIO-3,<
	EXP	^O15
	0
FREMES: >
IFE REALIO,<	DT"SIMULATED BASIC FOR THE 6502 V1.1"> ; 用于 6502 的模拟 BASIC V1.1
IFE REALIO-1,<	DT"KIM BASIC V1.1"> ; KIM BASIC V1.1
IFE REALIO-2,<	DT"OSI 6502 BASIC VERSION 1.1"> ; OSI 6502 BASIC 版本 1.1
IFE REALIO-3,<	DT"### COMMODORE BASIC ###" ; ### COMMODORE BASIC ###
	EXP	^O15
	EXP	^O15>
IFE	REALIO-4,<DT"APPLE BASIC V1.1"> ; APPLE BASIC V1.1
IFE	REALIO-5,<DT"STM BASIC V1.1"> ; STM BASIC V1.1
IFN	REALIO-3,<
	ACRLF
	DT"COPYRIGHT 1978 MICROSOFT" ; 版权所有 1978 MICROSOFT
	ACRLF>
	0
LASTWR::
	BLOCK	100		;SPACE FOR TEMP STACK. ; 临时堆栈空间
IFE REALIO,<
TSTACK::BLOCK	13600>

IF2,<
	PURGE	A,X,Y>
IFNDEF	START,<START==0>
	END	$Z+START